-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 독서 기록 플로우 UI/UX 개편 #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Walkthrough감정 리소스 및 칩 스타일/컴포넌트가 디자인 시스템에 추가되고, 기록 플로우에 감정 상세 선택 바텀시트와 인용문 입력(QuoteStepV2)이 도입되며 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
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧠 Learnings (2)📓 Common learnings📚 Learning: 2025-08-28T12:25:54.058ZApplied to files:
⏰ 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)
🔇 Additional comments (3)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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폴백은 방어적 프로그래밍이지만 필수는 아니며, 의도를 명확히 하려면 주석을 추가하는 것이 좋습니다.
...cord/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
Show resolved
Hide resolved
...record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt
Outdated
Show resolved
Hide resolved
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt
Outdated
Show resolved
Hide resolved
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ 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을 확인하도록 변경된 것이 적절합니다. 이를 통해 사용자가 감정과 상세 정보를 확정해야만 다음 단계로 진행할 수 있습니다.
| val bringIntoViewRequester = remember { BringIntoViewRequester() } | ||
| val keyboardState by rememberKeyboardVisible() | ||
| var isSentenceTextFieldFocused by remember { mutableStateOf(false) } | ||
|
|
||
| LaunchedEffect(keyboardState, isSentenceTextFieldFocused) { | ||
| if (keyboardState && isSentenceTextFieldFocused) { | ||
| delay(100) | ||
| bringIntoViewRequester.bringIntoView() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BringIntoViewRequester가 컴포저블에 연결되지 않았습니다.
BringIntoViewRequester가 생성되고 bringIntoView()가 호출되지만, 실제로 어떤 컴포저블에도 .bringIntoViewRequester(bringIntoViewRequester) modifier가 연결되지 않아 자동 스크롤이 작동하지 않습니다.
🔎 수정 제안
문장 입력 TextField를 감싸는 Box에 modifier를 추가하세요:
+ Box(
+ modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester)
+ ) {
ReedRecordTextField(
recordState = state.recordSentenceState,
recordHintRes = R.string.quote_step_sentence_hint,
modifier = Modifier
.fillMaxWidth()
.height(140.dp)
.onFocusChanged { focusState ->
isSentenceTextFieldFocused = focusState.isFocused
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Default,
),
)
+ }또는 필요한 import를 추가하세요:
import androidx.compose.foundation.relocation.bringIntoViewRequesterCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/QuoteStepV2.kt
around lines 64 to 72, the BringIntoViewRequester is created and bringIntoView()
is invoked but never attached to any composable; add the
.bringIntoViewRequester(bringIntoViewRequester) modifier to the Box (or the
container) that wraps the sentence input TextField (or the TextField itself) so
the requester is bound to a layout, and add the import
androidx.compose.foundation.relocation.bringIntoViewRequester if missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seoyoon513 현 시점에서 필요한 코드인지 확인이 필요할 것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
이 작업까지 완료되면 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이후 API로 받아오는 방식으로 대체 예정
|
문장 스캔 버튼 눌렀을때 갤러리에서 선택하는 옵션 추가 예정 |
easyhooon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 서버 작업 반영 후 이후 작업 진행하시죠~
🔗 관련 이슈
📙 작업 설명
디자인 시스템
기록 첫 번째 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.