[Feat] 감정 구슬 상세 화면 UI 구현#92
Conversation
Walkthrough감정별 그래픽과 설명 데이터가 추가되고, 감정 상세 화면이 날짜·설명·이미지를 표시하도록 확장되었습니다. 활동 기록 화면에는 디밍 오버레이와 조정된 시트 표시 설정이 적용되며, 감정 기록이 있는 날짜만 선택할 수 있습니다. Changes감정 상세 화면 흐름
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
Projects/Presentation/Sources/ActivityHistory/View/ActivityHistoryViewController.swift (1)
196-206: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
dimmedView가 고정 frame이라 회전/크기 변경 시 전체 화면을 덮지 못할 수 있습니다.
newDimmedView.frame = view.bounds로 한 번만 프레임을 지정하고 autoresizingMask나 오토레이아웃 제약이 없습니다. 디바이스 회전이나 사이즈 클래스 변경이 발생하면 오버레이가 새로운 bounds로 갱신되지 않아 화면 일부만 덮는 시각적 결함이 생길 수 있습니다. 코드베이스 전반에서 SnapKit을 사용하는 관례와도 일치하지 않습니다.♻️ 제안하는 수정
let newDimmedView = UIView() newDimmedView.backgroundColor = .black.withAlphaComponent(0.0) - newDimmedView.frame = view.bounds view.addSubview(newDimmedView) + newDimmedView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } dimmedView = newDimmedView🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/Presentation/Sources/ActivityHistory/View/ActivityHistoryViewController.swift` around lines 196 - 206, Update the dimmedView setup in the surrounding overlay presentation method so newDimmedView remains pinned to view’s edges after rotation and size changes. Replace the one-time frame assignment with the project’s established SnapKit constraints (or equivalent edge constraints), and ensure the view is configured for Auto Layout before constraining it; preserve the existing dimming animation.Projects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swift (1)
50-53: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
viewDidDisappear기반onDismiss호출은 "가려짐"과 "실제 dismiss"를 구분하지 못합니다.
viewDidDisappear는 실제 dismiss뿐 아니라 이 화면 위에 다른 화면(예: alert)이 추가로 present되어 가려지는 경우에도 호출됩니다. 현재 흐름에서는 문제가 없지만, 추후 이 화면에서 다른 화면을 present하게 되면ActivityHistoryViewController의dimmedView가 시트가 아직 떠 있는 상태에서 사라지는 버그가 발생할 수 있습니다.
UIAdaptivePresentationControllerDelegate.presentationControllerDidDismiss(_:)를 사용하면 실제 dismiss(스와이프 포함)에만 반응하여 더 안전합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swift` around lines 50 - 53, Replace the onDismiss call in ActivityHistoryViewController.viewDidDisappear with UIAdaptivePresentationControllerDelegate.presentationControllerDidDismiss(_:) so callbacks occur only after the presentation is actually dismissed, including interactive swipe dismissals. Make ActivityHistoryViewController conform to the delegate and invoke onDismiss from presentationControllerDidDismiss instead of viewDidDisappear.Projects/Presentation/Sources/EmotionRegister/Model/Emotion.swift (1)
204-239: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
emotionDescription와 기존description간 텍스트 중복
emotionDescription는description의 핵심 문구 앞에 "이날은 ___했나봐요! " 접두사를 붙인 형태입니다. 두 프로퍼티가 동일한 설명 텍스트를 각각 하드코딩하고 있어, 문구 수정 시 양쪽을 모두 업데이트해야 하는 유지보수 리스크가 있습니다.또한 CALM(Line 210), LETHARGY(Line 220), ANXIETY(Line 225) 케이스의 첫 번째 줄 끝에 후행 공백이 포함되어 있으며, VITALITY·SATISFACTION·FATIGUE에는 없어 일관성이 깨집니다. Swift 멀티라인 문자열 리터럴에서 후행 공백은 문자열에 포함되어 렌더링 시 미세한 레이아웃 차이를 유발할 수 있습니다.
♻️ 후행 공백 제거 제안
case .CALM: """ - 이날은 평온했나봐요! 평온함은 마음이 고요하고 + 이날은 평온했나봐요! 평온함은 마음이 고요하고 편안해 균형을 이루는 상태예요. """ case .VITALITY: """ 이날은 활기찼나봐요! 활기참은 생기가 가득 차 활발하고 적극적인 상태예요. """ case .LETHARGY: """ - 이날은 무기력했나봐요! 무기력함은 의욕이 없어 + 이날은 무기력했나봐요! 무기력함은 의욕이 없어 아무것도 하기 힘든 상태예요. """ case .ANXIETY: """ - 이날은 불안했나봐요! 불안함은 마음이 불안정하고 + 이날은 불안했나봐요! 불안함은 마음이 불안정하고 쉽게 안심하기 어려운 상태예요. """🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/Presentation/Sources/EmotionRegister/Model/Emotion.swift` around lines 204 - 239, Update emotionDescription to compose each emotion’s prefix with the existing description property instead of duplicating the description text, preserving the current output. Remove trailing spaces from the CALM, LETHARGY, and ANXIETY multiline string lines, and keep formatting consistent across all cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@Projects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swift`:
- Around line 106-109: Update the descriptionLabel constraints in
EmotionDetailViewController so its available width is bounded by adding a
trailing constraint or equivalent width constraint alongside the existing
leading constraint. Preserve the two-line numberOfLines configuration and ensure
the label wraps within the screen margins.
---
Nitpick comments:
In
`@Projects/Presentation/Sources/ActivityHistory/View/ActivityHistoryViewController.swift`:
- Around line 196-206: Update the dimmedView setup in the surrounding overlay
presentation method so newDimmedView remains pinned to view’s edges after
rotation and size changes. Replace the one-time frame assignment with the
project’s established SnapKit constraints (or equivalent edge constraints), and
ensure the view is configured for Auto Layout before constraining it; preserve
the existing dimming animation.
In
`@Projects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swift`:
- Around line 50-53: Replace the onDismiss call in
ActivityHistoryViewController.viewDidDisappear with
UIAdaptivePresentationControllerDelegate.presentationControllerDidDismiss(_:) so
callbacks occur only after the presentation is actually dismissed, including
interactive swipe dismissals. Make ActivityHistoryViewController conform to the
delegate and invoke onDismiss from presentationControllerDidDismiss instead of
viewDidDisappear.
In `@Projects/Presentation/Sources/EmotionRegister/Model/Emotion.swift`:
- Around line 204-239: Update emotionDescription to compose each emotion’s
prefix with the existing description property instead of duplicating the
description text, preserving the current output. Remove trailing spaces from the
CALM, LETHARGY, and ANXIETY multiline string lines, and keep formatting
consistent across all cases.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 10b3a6c2-cb51-457a-b3d4-179ec476a06a
⛔ Files ignored due to path filters (18)
Projects/Presentation/Resources/Images.xcassets/EmotionActivity/anxiety_emotion_graphic.imageset/anxiety_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/anxiety_emotion_graphic.imageset/anxiety_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/anxiety_emotion_graphic.imageset/anxiety_emotion_graphic@3x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/calm_emotion_graphic.imageset/calm_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/calm_emotion_graphic.imageset/calm_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/calm_emotion_graphic.imageset/calm_emotion_graphic@3x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/fatigue_emotion_graphic.imageset/fatigue_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/fatigue_emotion_graphic.imageset/fatigue_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/fatigue_emotion_graphic.imageset/fatigue_emotion_graphic@3x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/lethargy_emotion_graphic.imageset/lethargy_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/lethargy_emotion_graphic.imageset/lethargy_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/lethargy_emotion_graphic.imageset/lethargy_emotion_graphic@3x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/satisfaction_emotion_graphic.imageset/satisfaction_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/satisfaction_emotion_graphic.imageset/satisfaction_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/satisfaction_emotion_graphic.imageset/satisfaction_emotion_graphic@3x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/vitality_emotion_graphic.imageset/vitality_emotion_graphic.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/vitality_emotion_graphic.imageset/vitality_emotion_graphic@2x.pngis excluded by!**/*.pngProjects/Presentation/Resources/Images.xcassets/EmotionActivity/vitality_emotion_graphic.imageset/vitality_emotion_graphic@3x.pngis excluded by!**/*.png
📒 Files selected for processing (13)
Projects/Presentation/Resources/Images.xcassets/EmotionActivity/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/anxiety_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/calm_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/fatigue_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/lethargy_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/satisfaction_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Resources/Images.xcassets/EmotionActivity/vitality_emotion_graphic.imageset/Contents.jsonProjects/Presentation/Sources/ActivityHistory/View/ActivityHistoryViewController.swiftProjects/Presentation/Sources/ActivityHistory/View/Component/EmotionCalendarView.swiftProjects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swiftProjects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swiftProjects/Presentation/Sources/EmotionRegister/Model/Emotion.swiftProjects/Shared/Sources/Extension/Date+.swift
| descriptionLabel.snp.makeConstraints { make in | ||
| make.top.equalTo(headerStackView.snp.bottom) | ||
| make.leading.equalToSuperview().offset(Layout.horizontalMargin) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
descriptionLabel에 trailing/width 제약이 없어 2줄 줄바꿈이 깨질 수 있습니다.
numberOfLines = 2만 설정하고 leading만 고정되어 있어, 라벨의 preferredMaxLayoutWidth를 결정할 폭 제약이 없습니다. 이 경우 UILabel의 intrinsicContentSize는 줄바꿈 없는 한 줄 기준으로 계산되어 텍스트가 화면 우측으로 넘치거나 잘릴 수 있습니다(목업의 "이날은 평온했나봐요! 평온함은..." 2줄 표시와 다르게 렌더링될 위험).
🐛 제안하는 수정
descriptionLabel.snp.makeConstraints { make in
make.top.equalTo(headerStackView.snp.bottom)
make.leading.equalToSuperview().offset(Layout.horizontalMargin)
+ make.trailing.equalToSuperview().inset(Layout.horizontalMargin)
}📝 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.
| descriptionLabel.snp.makeConstraints { make in | |
| make.top.equalTo(headerStackView.snp.bottom) | |
| make.leading.equalToSuperview().offset(Layout.horizontalMargin) | |
| } | |
| descriptionLabel.snp.makeConstraints { make in | |
| make.top.equalTo(headerStackView.snp.bottom) | |
| make.leading.equalToSuperview().offset(Layout.horizontalMargin) | |
| make.trailing.equalToSuperview().inset(Layout.horizontalMargin) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@Projects/Presentation/Sources/ActivityHistory/View/EmotionDetailViewController.swift`
around lines 106 - 109, Update the descriptionLabel constraints in
EmotionDetailViewController so its available width is bounded by adding a
trailing constraint or equivalent width constraint alongside the existing
leading constraint. Preserve the two-line numberOfLines configuration and ensure
the label wraps within the screen margins.
🌁 Background
감정 구슬 기록 달력에서 감정을 누를 때 보이는 감정 구슬 상세 화면 UI를 구현했어요 ~
📱 Screenshot
👩💻 Contents
EmotionDetailViewController구현Summary by CodeRabbit
새로운 기능
개선 사항