Conversation
|
""" Walkthrough이 변경 사항은 기록장(그룹 노트) 페이지의 UI와 관련된 주요 컴포넌트와 화면을 신설 및 리팩토링합니다. 투표, 필터, 카드, 댓글 등 다양한 UI 요소의 데이터 구조와 레이아웃이 개선되고, 새로운 화면과 아이콘, 문자열 리소스가 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant GroupNoteScreen
participant FilterHeaderSection
participant ListView
participant TextCommentCard
participant VoteCommentCard
participant FloatingButton
User->>GroupNoteScreen: 화면 진입
GroupNoteScreen->>FilterHeaderSection: 필터/페이지 범위 입력
User->>FilterHeaderSection: 필터/페이지 범위 선택
FilterHeaderSection-->>GroupNoteScreen: 상태 변경 콜백
GroupNoteScreen->>ListView: 필터링된 mockGroupNoteItems 전달
ListView->>TextCommentCard: 텍스트 댓글 아이템 렌더링
ListView->>VoteCommentCard: 투표 댓글 아이템 렌더링
User->>FloatingButton: 새 기록 추가 버튼 클릭
FloatingButton-->>GroupNoteScreen: (아직 구현되지 않음)
Assessment against linked issues
Assessment against linked issues: Out-of-scope changes해당 변경 사항에서 명확히 범위를 벗어난 기능적 변경은 발견되지 않았습니다. Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
헉 저 일단 바텀시트 수정할라다가 문제가 좀 생겨서 커스텀으로 composable 함수 넣을 수 있게 새로 만들었어요 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt (1)
54-55: 포맷팅 개선 제안VoteItem 클래스 끝부분의 공백 라인을 정리하는 것이 좋겠습니다.
-} - +}app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt (1)
3-4: 패키지 간 의존성 검토 필요VoteItem을 note.mock 패키지에서 임포트하고 있습니다. 공통 데이터 모델은 별도의 공통 패키지로 이동하는 것을 고려해보세요.
app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt (1)
39-39: ProfileBar의 명시적 padding 설정ProfileBar에 명시적으로
Modifier.padding(0.dp)를 설정한 것은 일관성을 위한 것으로 보입니다. 하지만 0.dp padding은 기본적으로 아무런 효과가 없으므로 이 줄은 제거할 수 있습니다.ProfileBar( - modifier = Modifier.padding(0.dp), // profileImage = data.profileImageUrl,app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt (1)
52-52: 하드코딩된 필터 옵션필터 옵션들이 하드코딩되어 있습니다. 이전 리뷰에서 학습한 내용에 따르면 StringResource 사용을 선호하므로 strings.xml로 이동하는 것을 권장합니다.
- val filters = listOf("최신순", "인기순", "댓글 많은 순") + val filters = listOf( + stringResource(R.string.filter_latest), + stringResource(R.string.filter_popular), + stringResource(R.string.filter_most_commented) + )app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1)
38-42: 투표 상태 관리 로직 개선 고려현재 구현은 작동하지만,
voteItemStates와selectedIndexes의 이중 상태 관리가 복잡합니다. 더 간단한 접근 방식을 고려해보세요.더 간단한 상태 관리 방식:
- // 각 페이지별 상태 기억: 선택 인덱스, 선택 여부 포함한 voteItems - val selectedIndexes = remember { mutableStateMapOf<Int, Int?>() } - val voteItemStates = remember { - voteData.map { it.voteItems.toMutableStateList() }.toMutableStateList() - } + val votedPages = remember { mutableStateMapOf<Int, Int?>() }그리고
onOptionSelected에서:- onOptionSelected = { index -> - selectedIndexes[page] = if (selectedIndex == index) null else index - voteItemStates[page] = voteItems.mapIndexed { i, item -> - item.copy(isVoted = i == index && selectedIndex != index) - }.toMutableStateList() - } + onOptionSelected = { index -> + votedPages[page] = if (votedPages[page] == index) null else index + }Also applies to: 62-86
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt(0 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt(2 hunks)app/src/main/res/drawable/ic_information.xml(1 hunks)app/src/main/res/values/strings.xml(1 hunks)
💤 Files with no reviewable changes (1)
- app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt
🧰 Additional context used
🧠 Learnings (4)
app/src/main/res/values/strings.xml (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
🧬 Code Graph Analysis (1)
app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt (1)
app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt (1)
ProfileBar(33-114)
🔇 Additional comments (42)
app/src/main/res/drawable/ic_information.xml (1)
1-28: 정보 아이콘 구현이 올바릅니다벡터 드로어블 구현이 Android 가이드라인을 잘 따르고 있습니다. 아이콘 크기, 뷰포트, 스트로크 속성이 일관되게 설정되어 있습니다.
app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt (1)
46-114: 필터 버튼 리팩토링이 잘 되었습니다레이아웃 구조가 개선되었고, 고정 높이와 드롭다운 스타일링이 일관성 있게 적용되었습니다. Box 컨테이너 사용과 TopEnd 정렬이 적절합니다.
app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt (2)
15-15: isLocked 속성 추가가 적절합니다sealed class에 추상 속성을 추가하고 하위 클래스에서 구현하는 패턴이 올바릅니다.
56-121: 목 데이터 구성이 잘 되었습니다다양한 상태의 샘플 데이터를 제공하여 UI 테스트에 유용합니다. 잠금 상태와 일반 상태를 모두 포함하고 있어 블러 효과 테스트가 가능합니다.
app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt (2)
5-8: VoteData 구조 개선이 좋습니다VoteItem 리스트로 통합하여 데이터 구조가 더 일관되고 관리하기 쉬워졌습니다.
10-38: 목 데이터 중앙화가 잘 되었습니다mockVoteData 리스트를 통해 일관된 테스트 데이터를 제공하고 있습니다. 다양한 길이의 투표 옵션을 포함하여 UI 테스트에 유용합니다.
app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt (2)
17-17: 목 데이터 중앙화 적용이 좋습니다mockVoteData 사용으로 일관된 테스트 데이터 관리가 가능해졌습니다.
58-58: 프리뷰 함수 개선인라인 데이터 대신 중앙화된 목 데이터를 사용하여 코드가 더 간결해지고 유지보수성이 향상되었습니다.
app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt (2)
34-34: 목 데이터 중앙화로 코드 개선하드코딩된 투표 데이터를 중앙화된 목 데이터로 변경한 것은 좋은 개선입니다. 이는 코드 유지보수성을 향상시키고 일관성을 보장합니다.
Also applies to: 88-88
34-34: 중앙화된 mock 데이터 사용으로 개선됨인라인 데이터 구성에서 중앙화된
mockVoteData사용으로 변경된 것이 좋습니다. 이는 데이터 일관성과 유지보수성을 향상시킵니다.Also applies to: 88-88
app/src/main/res/values/strings.xml (2)
169-169: 사용자 친화적인 안내 메시지 추가진행도에 따른 댓글 블러 처리에 대한 명확한 안내 메시지를 추가한 것이 좋습니다. 사용자 경험 향상에 도움이 될 것입니다.
169-169: 문자열 리소스 추가가 적절함UI 텍스트를 문자열 리소스로 추출한 것이 좋습니다. 한국어 메시지도 적절하며, 리소스 이름도 명확합니다.
app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt (3)
41-41: 레이아웃 개선이지만 영향 확인 필요수직 패딩 제거는 레이아웃을 개선할 수 있지만, 다른 컴포넌트들과의 간격이 적절한지 확인해주세요.
64-64: 명시적 활성화 상태 제어 개선
enabled매개변수를 명시적으로 전달하여 버튼 상태를 더 명확하게 제어할 수 있게 되었습니다.
41-41: UI 레이아웃 개선이 적절함패딩을 수평으로만 제한하고
enabled파라미터를 명시적으로 전달하는 것이 좋습니다. 레이아웃 제어가 개선되고 코드가 더 명확해집니다.Also applies to: 64-64
app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt (2)
27-27: 컴포넌트 재사용성 개선
modifier매개변수를 추가하여 컴포넌트의 유연성과 재사용성을 향상시켰습니다. 이는 Compose 모범 사례를 따르는 좋은 개선입니다.Also applies to: 34-34
27-27: 컴포넌트 유연성 개선이 좋음
modifier파라미터 추가로 컴포넌트의 재사용성과 유연성이 향상되었습니다. 기본값 제공으로 하위 호환성도 유지됩니다.Also applies to: 34-34
app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (3)
38-42: 투표 상태 관리 개선각 페이지별로 투표 상태를 분리하여 관리하는 것은 좋은 개선입니다. 상태 관리가 더 명확해졌습니다.
112-112: 목 데이터 중앙화 개선프리뷰에서 하드코딩된 데이터를 중앙화된 목 데이터로 변경한 것은 좋은 개선입니다.
80-86: 투표 토글 로직 일관성 확인 완료
모든 onOptionSelected 구현(VoteCommentCard, GroupVoteButton, CardVote)에서 단일 선택/해제 토글이 의도대로 동작합니다.
- 동일 항목 재클릭 시 선택이 해제되고
- 다른 항목 선택 시 이전 선택이 초기화된 후 새로운 항목에만 isVoted가 적용됩니다.
확인된 위치:
- app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt
- app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt
- app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt
추가 수정 불필요합니다.
app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt (3)
5-5: Import 추가 승인컴포넌트의 확장성과 blur 효과를 위한 필요한 import들이 적절히 추가되었습니다.
Also applies to: 12-12, 13-13
27-27: modifier 매개변수와 blur 효과 구현 승인컴포넌트의 재사용성을 높이는 modifier 매개변수 추가와 isLocked 상태에 따른 blur 효과 적용이 적절하게 구현되었습니다. 5.dp blur 값과 padding 값도 일관성 있게 설정되었습니다.
Also applies to: 33-35
83-83: 프리뷰에서 isLocked 속성 추가 승인프리뷰에서 isLocked = false 설정으로 새로운 속성을 적절히 반영했습니다.
app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt (6)
1-26: 새로운 VoteCommentCard 컴포넌트 구현 승인필요한 모든 imports와 패키지 선언이 적절히 구성되었습니다. 투표 댓글 카드 기능을 위한 의존성들이 올바르게 import되었습니다.
27-36: 컴포넌트 매개변수와 상태 관리 구현 승인컴포넌트의 매개변수 설정과 상태 관리가 잘 구현되었습니다:
- modifier 매개변수로 재사용성 확보
- 적절한 상태 변수들 (isLiked, selected, voteItems)
- hasVoted 파생 상태 계산이 올바름
37-52: 레이아웃과 ProfileBar 구현 승인TextCommentCard와 일관된 레이아웃 구조를 유지하며, blur 효과 적용도 동일하게 구현되었습니다. ProfileBar의 구성도 적절합니다.
54-79: 투표 기능 구현 승인투표 로직이 올바르게 구현되었습니다:
- 토글 기능 (재선택 시 취소)
- 상태 업데이트 로직이 정확함
- GroupVoteButton과의 연동이 적절함
81-91: ActionBarButton 구현 승인좋아요와 댓글 기능을 위한 ActionBarButton 구성이 TextCommentCard와 일관되게 구현되었습니다.
93-116: 프리뷰 함수 구현 승인프리뷰 함수가 적절한 샘플 데이터와 함께 잘 구현되었습니다. 다양한 테스트 케이스를 포함한 VoteItem 리스트가 제공되어 있습니다.
app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt (7)
28-28: VoteItem import 추가 승인데이터 구조 통합을 위한 VoteItem import가 적절히 추가되었습니다.
36-39: 매개변수 리팩토링 승인기존의 분리된
options와voteResults리스트를voteItems단일 리스트로 통합하고,hasVoted매개변수를 명시적으로 추가한 것은 더 명확하고 일관된 API를 제공합니다.
42-42: fillMaxWidth 수정자 추가 승인컴포넌트의 레이아웃 일관성을 위한
fillMaxWidth수정자 추가가 적절합니다.
45-47: VoteItem 속성 사용 승인
VoteItem객체의 속성을 사용하여 투표 백분율을 가져오는 로직이 올바르게 구현되었습니다.
76-76: null 허용 콜백 변경 승인선택 취소 기능을 위한 null 허용 콜백 변경이 적절합니다.
102-102: VoteItem 속성 표시 승인UI 텍스트에서
VoteItem의itemName과percentage속성을 사용하도록 변경된 것이 적절합니다.Also applies to: 108-108
123-152: 프리뷰 함수 업데이트 승인프리뷰 함수가 새로운 VoteItem 데이터 구조와 상태 관리 로직을 반영하여 적절히 업데이트되었습니다. 투표 상태 토글 로직도 올바르게 구현되었습니다.
app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt (6)
1-40: GroupNoteScreen 컴포넌트 구현 승인새로운 기록장 화면을 위한 모든 필요한 imports와 패키지 선언이 적절히 구성되었습니다.
41-58: 상태 관리와 필터링 로직 구현 승인화면에 필요한 다양한 상태 변수들과 필터링 로직이 적절히 구현되었습니다:
- 탭 선택 상태 관리
- 페이지 범위 필터 상태
- 정렬 필터 상태
- 탭별 아이템 필터링 로직
60-73: 상단 앱바와 탭 구현 승인DefaultTopAppBar와 HeaderMenuBarTab의 구성이 적절하며, 탭 선택 로직도 올바르게 구현되었습니다.
75-112: LazyColumn과 아이템 렌더링 승인LazyColumn을 사용한 리스트 렌더링과 아이템 타입별 조건부 렌더링이 잘 구현되었습니다:
- 정보 아이콘과 텍스트 표시
- GroupNoteRecord와 GroupNoteVote 타입별 적절한 카드 컴포넌트 사용
114-142: 필터 버튼과 플로팅 버튼 구현 승인FilterButton과 FilterHeaderSection, FloatingButton의 배치와 구성이 적절합니다. Box를 사용한 레이아웃 설정도 올바릅니다.
145-151: 프리뷰 함수 구현 승인프리뷰 함수가 ThipTheme과 함께 적절히 구현되었습니다.
|
이거 궁금한게 그 탑쪽에 약간 이상한 디자인의 버튼들은 고정인가요? ㅋㅋㅋ |
rbqks529
left a comment
There was a problem hiding this comment.
코드 전부 확인했도 이전 바이패스 한 pr도 확인해보겠습니다!
| onLastPageChange = { lastPage = it }, | ||
| onTotalToggle = { isTotalSelected = !isTotalSelected }, | ||
| ) | ||
| } |
There was a problem hiding this comment.
혹시 필터 버튼을 column으로 해서 순서대로 안하고 box로 마지막에 선언하신 이유가 있을까요?
There was a problem hiding this comment.
이거 처음에는 column으로 했었는데 그럼 필터 부분이 영역을 차지하게 돼서 필터가 열리면 화면 전체가 아래로 밀리더라구요
그래서 공간을 안차지하게 하려면 material에서 제공해주는 Dropdown 컴포넌트를 사용해야하는데, 그렇게 되면 디자인에 제약이 걸려서 .. 커스텀을 하면서 공간을 차지하지 않게 하기 위해 이런 막되먹은 코드가 탄생했답니다
| var totalEnabled by rememberSaveable { mutableStateOf(false) } | ||
|
|
||
| var selectedFilter by rememberSaveable { mutableStateOf("최신순") } | ||
| val filters = listOf("최신순", "인기순", "댓글 많은 순") |
There was a problem hiding this comment.
저도 이런 코드가 있어서 그런데 이런 string은 추출하는게 좋을까요? 아니면 임시로 이렇게 두는게 좋을까요?
There was a problem hiding this comment.
저도 처음에 고민했었는데 어차피 사라질 애들일거같아서 그냥 냅뒀습니다 .ㅎ..ㅎ..
There was a problem hiding this comment.
오잉 얘네 사라질 애들인가요?? 필터링 기준이 아직 확정이 아닌겅가요?
There was a problem hiding this comment.
저거 서버에서 값을 보내줄거가타서욧 ..! 아마도 ?? 정렬 기능도 서버에서 해주지 않을까욧 ..!?
There was a problem hiding this comment.
아항 근데 먼가 저 드롭버튼은 사용자가 자주 선택을 바꿀 것 같아서 매번 요청 보내는 것보다 클라에서 바로바로 처리 가능한게 더 낫지않을까 생각하긴 했는데,, 요건 확정이 아니라면 회의때 더 이야기해봐도 좋을 것 같아욧
There was a problem hiding this comment.
아 그건 그렇긴 한데 이게 쓰이는 화면이 아마 무한스크롤 형태일건데 그럼 무조건 서버에서 처리를 해야해요 ㅠ
There was a problem hiding this comment.
엄,, 이거 다시 보니까 코드만 봤을땐 드롭다운 바깥 영역 터치했을 때 드롭다운이 닫히거나 하진 않죠,,?
그런 기능이 필요할 것 같아용 ~ 현재 잇는 box 바깥에 화면 전체 영역을 덮는 box (투명하게) 를 두고, 터치하면 expanded가 false가 되도록 하면 될 것 같은데.. 상상코딩이라 될지는 잘 모르겠네여 한번 부탁드립니닷
| // hoursAgo = data.postDate | ||
| hoursAgo = data.postDate |
There was a problem hiding this comment.
아 저거 원래 제가 데이터 구조를 string으로 하고 아래쪽을 int -> toString으로 해서 위에걸로 바꿔라! 라는걸 표시한거였는데 코딩 하다보니까 뭐가 사라지고 막 이래서 .. 저런식으로 남았나봐용 ㅋㅎㅋㅎㅋㅎ 수정하겠습니닷
| var totalEnabled by rememberSaveable { mutableStateOf(false) } | ||
|
|
||
| var selectedFilter by rememberSaveable { mutableStateOf("최신순") } | ||
| val filters = listOf("최신순", "인기순", "댓글 많은 순") |
There was a problem hiding this comment.
오잉 얘네 사라질 애들인가요?? 필터링 기준이 아직 확정이 아닌겅가요?
| var totalEnabled by rememberSaveable { mutableStateOf(false) } | ||
|
|
||
| var selectedFilter by rememberSaveable { mutableStateOf("최신순") } | ||
| val filters = listOf("최신순", "인기순", "댓글 많은 순") |
…into ui/THIP-TextHip#33-group_note_page # Conflicts: # app/src/main/java/com/texthip/thip/ui/common/bottomsheet/CustomBottomSheet.kt # app/src/main/res/values/strings.xml
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt (1)
71-83: ReplyItem 수동 생성 대신 데이터 변환 함수 사용 권장과거 리뷰에서 지적된 것과 동일한 이슈입니다. CommentItem에서 ReplyItem으로 수동 변환하는 코드가 복잡하고 오류가 발생하기 쉽습니다.
🧹 Nitpick comments (1)
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt (1)
34-34: 고정 높이 사용 검토 필요482.dp의 고정 높이를 사용하고 있습니다. 다양한 화면 크기와 댓글 수에 대응하기 위해 반응형 높이 설정을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
.idea/misc.xml(0 hunks)app/src/main/java/com/texthip/thip/ui/common/bottomsheet/CustomBottomSheet.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt(1 hunks)app/src/main/res/values/strings.xml(1 hunks)
💤 Files with no reviewable changes (1)
- .idea/misc.xml
✅ Files skipped from review due to trivial changes (3)
- app/src/main/java/com/texthip/thip/ui/common/bottomsheet/CustomBottomSheet.kt
- app/src/main/res/values/strings.xml
- app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt
- app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt
- app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt (1)
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
🧬 Code Graph Analysis (1)
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt (3)
app/src/main/java/com/texthip/thip/ui/common/bottomsheet/CustomBottomSheet.kt (1)
CustomBottomSheet(44-129)app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt (1)
CommentList(23-51)app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt (1)
CommentTextField(40-146)
🔇 Additional comments (2)
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt (1)
1-85: 댓글 바텀시트 컴포넌트 구현이 잘 되어 있습니다전반적으로 코드 구조가 깔끔하고 상태 관리가 적절하게 구현되어 있습니다. CustomBottomSheet를 활용한 구현과 댓글 입력/답글 기능이 잘 통합되어 있습니다.
app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt (1)
100-116: 프리뷰 함수 구현이 적절합니다테스트용 데이터와 함께 프리뷰 함수가 잘 구현되어 있어 개발 시 UI 확인에 도움이 됩니다.
| CustomBottomSheet( | ||
| onDismiss = onDismiss, | ||
| ) { | ||
| items.forEachIndexed { index, item -> | ||
| if (index > 0) { | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| } | ||
| .zIndex(1f) // 다른 컴포넌트 위에 뜨도록 | ||
| ) | ||
|
|
||
|
|
||
| // BottomSheet 본체 | ||
| Box( | ||
| modifier = Modifier | ||
| .fillMaxSize() | ||
| .zIndex(2f), // 시트가 배경보다 위에 뜨도록 | ||
| contentAlignment = Alignment.BottomCenter | ||
| ) { | ||
| Box( | ||
| modifier = Modifier | ||
| .fillMaxWidth() | ||
| .offset(y = (offsetY + animatableOffset.value).dp) | ||
| .background( | ||
| color = colors.DarkGrey, | ||
| shape = RoundedCornerShape(topEnd = 12.dp, topStart = 12.dp) | ||
| ) | ||
| .padding(20.dp) | ||
| .pointerInput(Unit) { | ||
| detectVerticalDragGestures( | ||
| onVerticalDrag = { _, dragAmount -> | ||
| if (dragAmount > 0) { | ||
| offsetY += dragAmount / 2 // 아래로 드래그할 때만 적용 | ||
| } | ||
| }, | ||
| onDragEnd = { | ||
| if (offsetY > 100f && !isDismissing) { | ||
| isDismissing = true | ||
| scope.launch { | ||
| animatableOffset.animateTo(300f, tween(300)) | ||
| onDismiss() | ||
| } | ||
| } else { | ||
| offsetY = 0f | ||
| } | ||
| Column( | ||
| modifier = Modifier | ||
| .height(50.dp) | ||
| .padding(horizontal = 12.dp, vertical = 8.dp), | ||
| verticalArrangement = Arrangement.Center | ||
| ) { | ||
| Text( | ||
| text = item.text, | ||
| style = typography.menu_m500_s16_h24, | ||
| color = item.color, | ||
| modifier = Modifier | ||
| .fillMaxWidth() | ||
| .clickable { | ||
| item.onClick() | ||
| onDismiss() | ||
| } | ||
| ) | ||
| } | ||
| .clickable(enabled = true) {} // 내부 클릭 무시되지 않도록 | ||
| ) { | ||
| Column(modifier = Modifier.fillMaxWidth()) { | ||
| items.forEachIndexed { index, item -> | ||
| if (index > 0) { | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| } | ||
|
|
||
| Column( | ||
| modifier = Modifier | ||
| .height(50.dp) | ||
| .padding(horizontal = 12.dp, vertical = 8.dp), | ||
| verticalArrangement = Arrangement.Center | ||
| ) { | ||
| Text( | ||
| text = item.text, | ||
| style = typography.menu_m500_s16_h24, | ||
| color = item.color, | ||
| modifier = Modifier | ||
| .fillMaxWidth() | ||
| .clickable { | ||
| item.onClick() | ||
| onDismiss() | ||
| } | ||
| ) | ||
| } | ||
| } | ||
| ) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
CustomBottomSheet 위임은 좋지만 UI/UX 개선이 필요합니다
CustomBottomSheet로 리팩토링한 것은 복잡한 상태 관리를 제거하고 코드를 단순화하는 좋은 접근입니다. 하지만 몇 가지 개선사항이 있습니다:
- 클릭 영역 확대: 현재 Text에만 clickable이 적용되어 있어 사용자 경험이 제한적입니다.
- 고정 높이 제거: 50.dp 고정 높이는 텍스트 길이에 따라 유연하지 않을 수 있습니다.
다음과 같이 개선하는 것을 제안합니다:
- Column(
- modifier = Modifier
- .height(50.dp)
- .padding(horizontal = 12.dp, vertical = 8.dp),
- verticalArrangement = Arrangement.Center
- ) {
- Text(
- text = item.text,
- style = typography.menu_m500_s16_h24,
- color = item.color,
- modifier = Modifier
- .fillMaxWidth()
- .clickable {
- item.onClick()
- onDismiss()
- }
- )
- }
+ Text(
+ text = item.text,
+ style = typography.menu_m500_s16_h24,
+ color = item.color,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable {
+ item.onClick()
+ onDismiss()
+ }
+ .padding(horizontal = 12.dp, vertical = 16.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.
| CustomBottomSheet( | |
| onDismiss = onDismiss, | |
| ) { | |
| items.forEachIndexed { index, item -> | |
| if (index > 0) { | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| } | |
| .zIndex(1f) // 다른 컴포넌트 위에 뜨도록 | |
| ) | |
| // BottomSheet 본체 | |
| Box( | |
| modifier = Modifier | |
| .fillMaxSize() | |
| .zIndex(2f), // 시트가 배경보다 위에 뜨도록 | |
| contentAlignment = Alignment.BottomCenter | |
| ) { | |
| Box( | |
| modifier = Modifier | |
| .fillMaxWidth() | |
| .offset(y = (offsetY + animatableOffset.value).dp) | |
| .background( | |
| color = colors.DarkGrey, | |
| shape = RoundedCornerShape(topEnd = 12.dp, topStart = 12.dp) | |
| ) | |
| .padding(20.dp) | |
| .pointerInput(Unit) { | |
| detectVerticalDragGestures( | |
| onVerticalDrag = { _, dragAmount -> | |
| if (dragAmount > 0) { | |
| offsetY += dragAmount / 2 // 아래로 드래그할 때만 적용 | |
| } | |
| }, | |
| onDragEnd = { | |
| if (offsetY > 100f && !isDismissing) { | |
| isDismissing = true | |
| scope.launch { | |
| animatableOffset.animateTo(300f, tween(300)) | |
| onDismiss() | |
| } | |
| } else { | |
| offsetY = 0f | |
| } | |
| Column( | |
| modifier = Modifier | |
| .height(50.dp) | |
| .padding(horizontal = 12.dp, vertical = 8.dp), | |
| verticalArrangement = Arrangement.Center | |
| ) { | |
| Text( | |
| text = item.text, | |
| style = typography.menu_m500_s16_h24, | |
| color = item.color, | |
| modifier = Modifier | |
| .fillMaxWidth() | |
| .clickable { | |
| item.onClick() | |
| onDismiss() | |
| } | |
| ) | |
| } | |
| .clickable(enabled = true) {} // 내부 클릭 무시되지 않도록 | |
| ) { | |
| Column(modifier = Modifier.fillMaxWidth()) { | |
| items.forEachIndexed { index, item -> | |
| if (index > 0) { | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| } | |
| Column( | |
| modifier = Modifier | |
| .height(50.dp) | |
| .padding(horizontal = 12.dp, vertical = 8.dp), | |
| verticalArrangement = Arrangement.Center | |
| ) { | |
| Text( | |
| text = item.text, | |
| style = typography.menu_m500_s16_h24, | |
| color = item.color, | |
| modifier = Modifier | |
| .fillMaxWidth() | |
| .clickable { | |
| item.onClick() | |
| onDismiss() | |
| } | |
| ) | |
| } | |
| } | |
| ) | |
| } | |
| } | |
| } | |
| CustomBottomSheet( | |
| onDismiss = onDismiss, | |
| ) { | |
| items.forEachIndexed { index, item -> | |
| if (index > 0) { | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | |
| Spacer(modifier = Modifier.height(8.dp)) | |
| } | |
| Text( | |
| text = item.text, | |
| style = typography.menu_m500_s16_h24, | |
| color = item.color, | |
| modifier = Modifier | |
| .fillMaxWidth() | |
| .clickable { | |
| item.onClick() | |
| onDismiss() | |
| } | |
| .padding(horizontal = 12.dp, vertical = 16.dp) | |
| ) | |
| } | |
| } |
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt
between lines 27 and 56, improve the UI/UX by expanding the clickable area from
just the Text to the entire Column to make it easier for users to tap. Also,
remove the fixed height of 50.dp on the Column to allow the height to adjust
dynamically based on the text content. Apply the clickable modifier to the
Column and eliminate the height modifier to achieve these improvements.
app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt
Show resolved
Hide resolved
| @Composable | ||
| fun CommentSection( | ||
| commentItem: CommentItem, | ||
| fun CommentList( |
There was a problem hiding this comment.
제가 잘 못 이해한 걸 수도 있는데 CommentSection -> CommentList로 이름을 변경한 컴포즈 함수를 만들었는데 CommentList 안에 CommentSection이 있는 게 맞는 걸까요?
There was a problem hiding this comment.
아 이거 처음엔 CommentSection만 필요하다고 생각했는데 CommentList도 필요하다고 생각돼서 추가했는데 파일 명을 못바꿨네요 다음 pr에서 리팩해서 반영하겠습니닷 !
rbqks529
left a comment
There was a problem hiding this comment.
댓글 바텀시트 만드신거 확인했습니다! 생각보다 복잡해보였는데 깔끔하게 만들어주셨네요
| val color: Color = Color.White, | ||
| val onClick: () -> Unit, | ||
| ) | ||
|
|
There was a problem hiding this comment.
CustomBottomSheet 으로 기존 것도 수정해주셨네요 확인했습니다!
➕ 이슈 링크
🔎 작업 내용
📸 스크린샷
기록장 페이지
2025-07-08.4.52.48.mov
댓글 바텀시트
2025-07-10.4.04.39.mov
😢 해결하지 못한 과제
댓글 바텀시트는 규빈이 pr 머지되면 작업하겠습니다
📢 리뷰어들에게
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
테스트/미리보기