Conversation
Walkthrough디자인 시스템에 감정용 리소스·칩 스타일·컴포넌트가 추가되고, 기록 플로우에 감정 상세 선택 바텀시트와 Step V2(감정/인용문) UI가 도입되며 RecordRegister의 상태와 이벤트가 확장되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as EmotionStepV2
participant Presenter as RecordRegisterPresenter
participant State as RecordRegisterUiState
participant Sheet as EmotionDetailBottomSheet
User->>UI: 감정 선택(탭)
UI->>Presenter: eventSink(OnSelectEmotionV2(emotion))
Presenter->>Presenter: provide/getEmotionDetails(emotion)
Presenter->>State: set emotionDetails, isEmotionDetailBottomSheetVisible=true, committedEmotion
State-->>UI: 상태 반영 → 바텀시트 표시
User->>Sheet: 상세 감정 토글/제거
Sheet->>Presenter: OnEmotionDetailToggled / OnEmotionDetailRemoved
Presenter->>State: update selectedEmotionDetails
State-->>Sheet: 선택 반영
alt 사용자 건너뛰기
User->>Sheet: 건너뛰기
Sheet->>Presenter: OnEmotionDetailSkipped
Presenter->>State: clear/commit defaults, isEmotionDetailBottomSheetVisible=false
else 선택 완료
User->>Sheet: 선택 완료
Sheet->>Presenter: OnEmotionDetailCommitted
Presenter->>State: commit selectedEmotionDetails, isEmotionDetailBottomSheetVisible=false
end
State-->>UI: 변경 반영
UI->>User: UI 업데이트
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
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: 4
🧹 Nitpick comments (4)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedRemovableChip.kt (1)
52-61: 닫기 아이콘의 터치 영역이 작을 수 있습니다.현재 아이콘 크기가 14.dp로 설정되어 있어 터치 타겟으로는 작을 수 있습니다. Android 접근성 가이드라인에서는 최소 48dp의 터치 영역을 권장합니다.
Modifier.size()와 별도로 터치 영역을 확장하거나, 현재 구현이 의도된 것인지 확인해 주세요.🔎 터치 영역 확장 제안
Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_close), contentDescription = "Icon Close", tint = ReedTheme.colors.contentBrand, modifier = Modifier .size(14.dp) + .padding(ReedTheme.spacing.spacing2) // 터치 영역 확장 .noRippleClickable { onRemove() }, )feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.kt (1)
54-57: 불필요한 람다 래핑을 제거할 수 있습니다.
onDismissRequest콜백을 직접 전달할 수 있습니다.🔎 제안된 수정
ReedBottomSheet( - onDismissRequest = { - onDismissRequest() - }, + onDismissRequest = onDismissRequest, sheetState = sheetState, ) {feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
98-102: 아이콘에 따른 contentDescription 업데이트가 필요합니다.
iconRes가isSelected상태에 따라 체크 아이콘 또는 chevron 아이콘으로 변경되지만,contentDescription은 항상 "Chevron Right"로 고정되어 있습니다. 접근성을 위해 상태에 맞는 설명을 제공하는 것이 좋습니다.🔎 제안된 수정
+ val iconContentDescription = if (isSelected) "Selected" else "Chevron Right" + Icon( imageVector = ImageVector.vectorResource(iconRes), - contentDescription = "Chevron Right", + contentDescription = iconContentDescription, tint = iconTint, )feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt (1)
120-124: 바텀시트 숨김 후 이벤트 전달 패턴 개선 고려바텀시트를 숨기는 패턴이 여러 곳에서 반복됩니다 (lines 120-124, 129-133, 135-140).
emotionDetailBottomSheetState.hide()를 호출한 후 이벤트를 전달하는 헬퍼 함수를 만들면 코드 중복을 줄일 수 있습니다.🔎 제안: 헬퍼 함수로 리팩토링
suspend fun hideBottomSheetAndDispatch(event: RecordRegisterUiEvent) { emotionDetailBottomSheetState.hide() state.eventSink(event) } // 사용 예시 onCloseButtonClick = { coroutineScope.launch { hideBottomSheetAndDispatch(RecordRegisterUiEvent.OnEmotionDatilBottomSheetDismiss) } }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt(1 hunks)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ChipSizeStyle.kt(1 hunks)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedRemovableChip.kt(1 hunks)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedSelectableChip.kt(1 hunks)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Spacing.kt(1 hunks)core/designsystem/src/main/res/values/strings.xml(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt(8 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt(2 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt(1 hunks)feature/record/src/main/res/values/strings.xml(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
📚 Learning: 2025-07-31T23:17:40.054Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
core/designsystem/src/main/res/values/strings.xmlfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.ktfeature/record/src/main/res/values/strings.xmlfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
🧬 Code graph analysis (6)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt (4)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
EmotionItem(41-124)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.kt (1)
EmotionDetailBottomSheet(39-149)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.kt (4)
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedBottomSheet.kt (1)
ReedBottomSheet(21-40)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedSelectableChip.kt (1)
ReedSelectableChip(20-54)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedRemovableChip.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (2)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedRemovableChip.kt (1)
ReedRemovableChip(25-63)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (3)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/textfield/ReedRecordTextField.kt (1)
ReedRecordTextField(42-129)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedSelectableChip.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: ci-build
- GitHub Check: Compose Stability Check
🔇 Additional comments (16)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Spacing.kt (1)
12-12: LGTM!기존 네이밍 컨벤션(
spacing05패턴)을 따르고 있으며, 4.dp와 8.dp 사이의 6.dp 값이 적절하게 추가되었습니다.core/designsystem/src/main/res/values/strings.xml (1)
7-10: LGTM!감정 설명 문자열이 일관된 형식으로 잘 추가되었습니다.
Emotion.descriptionRes확장 프로퍼티와 연동되어 사용됩니다.feature/record/src/main/res/values/strings.xml (1)
45-49: LGTM!감정 상세 선택 UI를 위한 문자열이 적절하게 추가되었습니다.
emotion_detail_title의%1$s포맷 문자열도 올바르게 사용되었습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionDetailBottomSheet.kt (2)
94-102: FlowRow의 수평 패딩이 중복될 수 있습니다.상위 Column에 이미
start와end에spacing5패딩이 적용되어 있습니다 (라인 62-66). FlowRow에도 동일한 수평 패딩이 추가되어 있어 총 40dp의 수평 여백이 생깁니다. 의도된 디자인인지 확인해 주세요.
120-146: LGTM!버튼 구성이 적절합니다. 확인 버튼의
enabled로직이selectedEmotionDetail.isNotEmpty()로 올바르게 구현되었습니다.core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedSelectableChip.kt (1)
20-54: LGTM!선택 상태에 따른 색상 로직이 명확하게 구현되었습니다.
ReedRemovableChip과 일관된 스타일 패턴을 따르고 있습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
41-74: LGTM!EmotionItem의 레이아웃 구조와 조건부 border 처리가
Modifier.then()을 사용하여 깔끔하게 구현되었습니다.core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt (1)
38-52: 확장 프로퍼티 구현이 적절합니다
graphicResV2와descriptionRes확장 프로퍼티가 모든Emotion값에 대해 exhaustive when 표현식을 사용하고 있어, 향후 새로운 감정 타입이 추가될 때 컴파일러가 누락된 분기를 감지할 수 있습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (1)
68-73: 키보드 표시 시 스크롤 처리가 적절합니다키보드가 표시되고 문장 입력 필드가 포커스되었을 때
bringIntoView()를 호출하여 필드를 화면에 표시하는 로직이 잘 구현되어 있습니다. 100ms 딜레이는 키보드 애니메이션과의 동기화를 위한 일반적인 패턴입니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt (1)
19-26: 감정 상세 상태 필드 추가가 적절합니다새로운 감정 상세 선택 기능을 위한 상태 필드들이 잘 구성되어 있습니다.
selectedEmotionDetails와committedEmotionDetails를 분리하여 임시 선택과 확정을 구분한 설계가 좋습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (4)
177-184: 하드코딩된 감정 상세 데이터 확인감정 상세 옵션이 하드코딩되어 있습니다. PR 설명에 따르면 서버 API 준비 전까지 임시로 사용하는 것으로 이해됩니다. API 연동 시 이 데이터를 실제 서버 응답으로 교체해야 합니다.
Based on learnings, Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하는 방식을 사용합니다.
267-275: 감정 상세 커밋 시 기존 선택 덮어쓰기 확인Line 272에서
committedEmotionDetails를 새로운 맵으로 교체하고 있습니다. 만약 사용자가 여러 감정을 선택할 수 있다면, 이전에 선택한 다른 감정의 상세 정보가 손실될 수 있습니다. 현재 설계에서는 한 번에 하나의 감정만 선택 가능한지 확인이 필요합니다.UI 플로우 상 사용자가 여러 감정을 동시에 선택할 수 있는지 EmotionStepV2 구현을 확인해주세요. 만약 여러 감정 선택이 가능하다면 다음과 같이 수정이 필요합니다:
🔎 여러 감정 선택 지원 시 제안 수정
- committedEmotionDetails = mapOf(emotionKey to details) + committedEmotionDetails = committedEmotionDetails + (emotionKey to details)
117-121: 다음 버튼 활성화 조건이 적절합니다QUOTE 단계에서 메모가 선택 사항으로 변경되었고, EMOTION 단계에서
committedEmotion을 확인하도록 수정된 것이 PR 목표와 일치합니다.
250-257: OnEmotionDetailRemoved 핸들러의 로직은 올바릅니다칩 제거 기능은 의도대로 작동합니다. EmotionItem에 표시되는 칩들은
committedEmotionDetails에서 가져오므로, 제거 시에도committedEmotionDetails에서 항목을 제거하는 것이 정확합니다.OnEmotionDetailToggled와 다르게 동작하는 이유는 두 핸들러가 다른 목적을 수행하기 때문입니다:selectedEmotionDetails는 바텀시트 내 임시 선택 상태이고,committedEmotionDetails는 이미 확정된 최종 상태입니다.core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ChipSizeStyle.kt (1)
22-29: 칩 스타일 정의가 적절합니다
ChipSizeStyle데이터 클래스와 두 가지 스타일 정의가 디자인 시스템 패턴을 잘 따르고 있습니다.smallChipStyle에서 사용하는spacing15는ReedSpacing에6.dp로 정의되어 있으며, 모든 참조가 올바르게 작동합니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt (1)
113-113: 바텀시트 표시 시selectedEmotionnull 가능성 검토코드 검증 결과,
OnSelectEmotionV2이벤트 핸들러가selectedEmotion을 설정한 직후isEmotionDetailBottomSheetVisible을true로 설정하는 원자적 작업이므로, 바텀시트가 표시될 때selectedEmotion이 null이 될 수 없습니다. 따라서 현재?: Emotion.WARM폴백은 방어적 프로그래밍이지만 필수는 아니며, 의도를 명확히 하려면 주석을 추가하는 것이 좋습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
112-120: 이전 리뷰 지적사항이 해결되었습니다.변수 섀도잉 문제가 수정되었습니다.
forEach람다의 변수명이detail로 변경되어 더 이상 컴포저블 파라미터emotion을 섀도잉하지 않습니다.
🧹 Nitpick comments (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
76-102: 접근성 문자열을 한국어로 변경하거나 문자열 리소스 사용을 고려해보세요.Line 78과 Line 100의
contentDescription이 영어로 되어 있습니다. 스크린 리더 사용자를 위해 한국어로 변경하거나 문자열 리소스(stringResource)를 사용하는 것이 좋습니다.🔎 제안된 수정
Image( painter = painterResource(emotion.graphicResV2), - contentDescription = "Emotion Image", + contentDescription = "감정 이미지", modifier = Modifier .size(60.dp) .clip(CircleShape)Icon( imageVector = ImageVector.vectorResource(iconRes), - contentDescription = "Chevron Right", + contentDescription = if (isSelected) "선택됨" else "선택 가능", tint = iconTint, )
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
core/designsystem/stability/designsystem.stability(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt(8 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt(2 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt(1 hunks)feature/record/src/main/res/values/strings.xml(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- feature/record/src/main/res/values/strings.xml
- feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionStepV2.kt
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
📚 Learning: 2025-07-31T23:17:40.054Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
📚 Learning: 2025-07-31T16:58:59.404Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: core/model/src/main/kotlin/com/ninecraft/booket/core/model/EmotionModel.kt:11-18
Timestamp: 2025-07-31T16:58:59.404Z
Learning: Reed-Android 프로젝트는 현재 다국어 지원 계획이 없어서 모델에 한글 문자열을 직접 포함하는 것이 허용된다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
🧬 Code graph analysis (2)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (2)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/chip/ReedRemovableChip.kt (1)
ReedRemovableChip(25-63)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (3)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/textfield/ReedRecordTextField.kt (1)
ReedRecordTextField(42-129)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: ci-build
- GitHub Check: Compose Stability Check
🔇 Additional comments (10)
core/designsystem/stability/designsystem.stability (1)
166-198: LGTM! 칩 컴포넌트의 안정성 선언이 올바르게 추가되었습니다.새로 추가된 칩 스타일과 컴포넌트들의 안정성 선언이 정확합니다:
- 모든 파라미터가
STABLE로 적절히 표시되어 Compose 재구성 최적화에 유리합니다.skippable: true와restartable: true설정으로 성능이 최적화되어 있습니다.- 기존 버튼 컴포넌트 패턴과 일관성을 유지하고 있습니다.
자동 생성된 파일이므로 향후 컴포넌트 시그니처 변경 시
./gradlew :designsystem:stabilityDump명령어를 재실행하여 업데이트하시면 됩니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)
41-141: 전반적인 구현이 우수합니다.
EmotionItem컴포저블이 잘 구현되었습니다:
- 디자인 시스템 토큰 사용이 일관적이고 정확합니다
- ImmutableList 사용으로 Compose 리컴포지션 최적화가 적용되었습니다
- 조건부 스타일링과 칩 표시 로직이 명확하게 분리되어 있습니다
- Preview 함수를 통해 디자인 타임 테스트가 가능합니다
- 전체적인 코드 구조가 깔끔하고 유지보수하기 좋습니다
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt (2)
19-26: 감정 상세 선택 워크플로우를 위한 상태 확장이 적절합니다.새로 추가된 상태 필드들이 감정 상세 선택 기능을 잘 지원하고 있습니다:
memoState: 메모 입력 상태emotionDetails: 선택 가능한 감정 상세 목록selectedEmotionDetails: 사용자가 선택한 감정별 상세 정보committedEmotion/committedEmotionDetails: 확정된 감정 및 상세 정보isEmotionDetailBottomSheetVisible: 바텀시트 표시 상태타입 안전성도
ImmutableList와Map을 사용하여 잘 확보되어 있습니다.
56-61: 감정 상세 선택을 위한 이벤트 정의가 잘 구성되어 있습니다.새로운 V2 이벤트들이 감정 선택 플로우를 명확하게 표현하고 있습니다:
OnSelectEmotionV2: 감정 선택 및 바텀시트 표시OnEmotionDetailToggled/OnEmotionDetailRemoved: 상세 감정 토글/제거OnEmotionDetailSkipped/OnEmotionDetailCommitted: 건너뛰기/확정OnEmotionDetailBottomSheetDismiss: 바텀시트 닫기과거 리뷰에서 지적된 오타(OnEmotionDatilBottomSheetDismiss)도 수정되었습니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (1)
88-228: 전체적인 UI 구성이 잘 되어 있습니다.QuoteStepV2 컴포넌트가 다음 요소들을 적절하게 구현하고 있습니다:
- 문장, 페이지, 메모 입력 필드들의 상태 관리
- 키보드 타입 및 IME 액션 설정
- 에러 처리 및 유효성 검증
- 포커스 관리 및 네비게이션
과거 리뷰에서 지적된 하드코딩 문자열 이슈도
stringResource를 사용하여 해결되었습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (5)
176-187: 감정 상세 정보 제공 로직이 적절합니다.하드코딩된 감정 상세 옵션들은 프로젝트의 개발 방식에 따라 허용됩니다. API 연동 시점에 실제 데이터로 교체될 예정입니다.
getEmotionDetails()함수는 안전한 fallback(persistentListOf())을 제공하여 null-safety를 보장합니다.Based on learnings, Reed-Android 프로젝트에서는 API 준비 전 UI를 먼저 구현하는 방식을 사용합니다.
231-235: 감정 선택 V2 핸들러가 잘 구현되어 있습니다.과거 리뷰에서 지적된 unsafe cast 이슈가
.toPersistentList()호출로 해결되었습니다. 로직이 명확합니다:
- 선택된 감정 설정
- 해당 감정의 상세 옵션 로드
- 상세 선택 바텀시트 표시
237-247: 상세 감정 토글 로직이 정확합니다.null 안전성을 확보하고 토글 동작(있으면 제거, 없으면 추가)이 올바르게 구현되어 있습니다.
249-278: 감정 상세 관리 핸들러들이 잘 구현되어 있습니다.각 핸들러가 명확한 책임을 가지고 있습니다:
OnEmotionDetailRemoved: 확정된 상세 감정 제거 및 선택 상태 동기화OnEmotionDetailSkipped: 상세 감정 없이 진행 (상태 초기화)OnEmotionDetailCommitted: 선택한 상세 감정 확정OnEmotionDetailBottomSheetDismiss: 바텀시트 닫기상태 동기화와 null 안전성이 잘 처리되어 있습니다.
119-121: 다음 버튼 활성화 조건이 새로운 워크플로우에 맞게 변경되었습니다.
EMOTION단계에서selectedEmotion대신committedEmotion을 확인하도록 변경된 것이 적절합니다. 이를 통해 사용자가 감정과 상세 정보를 확정해야만 다음 단계로 진행할 수 있습니다.
이 작업까지 완료되면 merge가 되는건가요 아니면 일단 merge 후 서버 API 반영 PR이 따로 올라오나여? |
요거 merge 후 서버 API 반영 때 추가해서 PR로 올리려구요! |
|
|
||
| fun provideEmotionDetailMap(): Map<Emotion, ImmutableList<String>> { | ||
| return mapOf( | ||
| Emotion.WARM to persistentListOf("위로받은", "포근한", "다정한", "고마운", "마음이 놓이는", "편안한"), |
There was a problem hiding this comment.
이후 API로 받아오는 방식으로 대체 예정
|
문장 스캔 버튼 눌렀을때 갤러리에서 선택하는 옵션 추가 예정 |
easyhooon
left a comment
There was a problem hiding this comment.
LGTM! 서버 작업 반영 후 이후 작업 진행하시죠~
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (3)
79-79: 테마 색상 사용 고려
White를 직접 사용하고 있습니다. 테마의 일관성을 위해ReedTheme.colors.bgPrimary또는 유사한 테마 색상 사용을 고려해보세요. 다만 디자인 시스템에서White를 직접 제공하는 경우라면 현재 방식도 적절합니다.
101-114: 하드코딩된 높이 값 고려TextField의 높이가
140.dp로 하드코딩되어 있습니다. 이러한 값을 디자인 시스템의 상수로 정의하거나 재사용 가능한 값으로 추출하면 유지보수가 용이해집니다. 메모 필드(208줄)에서도 동일한 높이를 사용하고 있어 공통 상수로 정의하면 좋을 것 같습니다.
134-201: "선택" 태그 UI 코드 중복 제거"선택" 태그를 표시하는 UI 코드가 페이지 섹션(144-156줄)과 메모 섹션(188-200줄)에서 중복됩니다. 재사용 가능한 Composable 함수로 추출하면 유지보수성이 향상됩니다.
🔎 제안하는 리팩토링
재사용 가능한 Composable 추출:
@Composable private fun OptionalLabel( labelText: String, modifier: Modifier = Modifier, ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier, ) { Text( text = labelText, color = ReedTheme.colors.contentPrimary, style = ReedTheme.typography.body1Medium, ) Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing2)) Text( text = stringResource(R.string.select), modifier = Modifier .clip(RoundedCornerShape(ReedTheme.radius.xs)) .background(color = ReedTheme.colors.bgSecondary) .padding( start = ReedTheme.spacing.spacing2, top = ReedTheme.spacing.spacing05, end = ReedTheme.spacing.spacing2, bottom = ReedTheme.spacing.spacing05, ), color = ReedTheme.colors.contentTertiary, style = ReedTheme.typography.caption1Medium, ) } }사용:
OptionalLabel(labelText = stringResource(R.string.quote_step_page_label)) // ... OptionalLabel(labelText = stringResource(R.string.quote_step_memo_label))
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
📚 Learning: 2025-07-31T23:17:40.054Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
📚 Learning: 2025-07-31T16:58:59.404Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: core/model/src/main/kotlin/com/ninecraft/booket/core/model/EmotionModel.kt:11-18
Timestamp: 2025-07-31T16:58:59.404Z
Learning: Reed-Android 프로젝트는 현재 다국어 지원 계획이 없어서 모델에 한글 문자열을 직접 포함하는 것이 허용된다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
📚 Learning: 2025-07-29T06:07:11.727Z
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.727Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
🧬 Code graph analysis (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (3)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/textfield/ReedRecordTextField.kt (1)
ReedRecordTextField(42-129)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Compose Stability Check
- GitHub Check: ci-build
🔇 Additional comments (2)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt (2)
216-231: 다음 버튼의 중복 클릭 방지 설정 확인
multipleEventsCutterEnabled = false로 설정되어 있어 버튼을 빠르게 여러 번 클릭할 수 있습니다. 일반적으로 "다음" 버튼은 중복 클릭 방지가 필요한 경우가 많은데, 이벤트가 다른 곳에서 중복 처리되거나 특별한 이유로 false로 설정한 것인지 확인이 필요합니다.
235-245: 프리뷰 구현 적절디자인 프리뷰가 적절하게 구성되어 있습니다.
ComponentPreview어노테이션과ReedTheme을 사용하여 일관된 미리보기 환경을 제공하고 있습니다.
🔗 관련 이슈
📙 작업 설명
디자인 시스템
기록 첫 번째 STEP
기록 두 번째 STEP
🧪 테스트 내역
📸 스크린샷 또는 시연 영상
Quote Step
Reed_.mp4
Emotion Step
Reed_._.mp4
💬 추가 설명 or 리뷰 포인트
RecordRegisterUi에서 아래 예시처럼 V2 컴포넌트로 임시 교체하여 확인해 주세요.Summary by CodeRabbit
새로운 기능
스타일/리소스
✏️ Tip: You can customize this high-level summary in your review settings.