Conversation
|
""" Walkthrough책 검색 및 상세, 모집중인 모임방 등 책 관련 UI 화면이 Jetpack Compose로 대규모 신규 구현되었습니다. 여러 데이터 클래스, 화면, 컴포넌트가 추가·리팩토링되었으며, string 리소스도 확장되었습니다. 기존 그룹 관련 컴포넌트들은 패키지 이동 및 네이밍 일관성 개선이 이루어졌습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant BookSearchScreen
participant BookFilteredSearchResult
participant BookLiveSearchResult
participant BookDetailScreen
User->>BookSearchScreen: 화면 진입/검색 입력
BookSearchScreen->>BookLiveSearchResult: 실시간 검색어 입력 시 결과 렌더링
User->>BookSearchScreen: 검색 확정(엔터/버튼)
BookSearchScreen->>BookFilteredSearchResult: 필터링된 결과 및 개수 전달
User->>BookFilteredSearchResult: 책 카드 클릭
BookFilteredSearchResult->>BookDetailScreen: 상세 정보 화면 이동
sequenceDiagram
participant User
participant BookDetailScreen
participant BookRecruitingScreen
User->>BookDetailScreen: 책 상세 화면 진입
User->>BookDetailScreen: '모집중인 모임방' 버튼 클릭
BookDetailScreen->>BookRecruitingScreen: 모집중인 그룹방 목록 표시
User->>BookRecruitingScreen: 새 모임방 생성 버튼 클릭
BookRecruitingScreen->>BookRecruitingScreen: 생성 콜백 실행
Possibly related issues
Possibly related PRs
Suggested labels
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ 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. 🪧 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 (
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (12)
app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt (1)
92-102: 코드 정리 제안북마크 기능을 주석 처리했지만, 관련 매개변수(
isBookmarked,onBookmarkClick)는 여전히 남아있습니다. 기능이 완전히 제거되는 것이라면 관련 매개변수도 함께 제거하거나, 임시적인 변경이라면 TODO 주석으로 명시하는 것이 좋겠습니다.임시 변경인 경우:
// 북마크 아이콘 제거(쓰는 화면이 안보임) + // TODO: 북마크 기능 구현 후 다시 활성화 /*IconButton(완전 제거인 경우 매개변수도 함께 제거 고려:
- isBookmarked: Boolean = false, - onBookmarkClick: () -> Unit = {}app/src/main/java/com/texthip/thip/ui/common/screen/RegisterBookScreen.kt (1)
62-64: Preview 함수명을 일관되게 수정하세요.함수명이
RegisterBookScreen으로 변경되었으나 Preview 함수명은 여전히GroupRegisterBookPreview로 되어 있습니다. 일관성을 위해RegisterBookScreenPreview로 변경해주세요.-private fun GroupRegisterBookPreview() { +private fun RegisterBookScreenPreview() {app/src/main/java/com/texthip/thip/ui/common/buttons/ActionMediumButton.kt (1)
40-40: 아이콘 선택 로직이 적절하게 구현되었습니다.
hasRightPlusIcon매개변수를 통해 우측 아이콘을 유연하게 선택할 수 있도록 구현이 잘 되어 있습니다.향후 아이콘 종류가 더 많아진다면 enum을 사용하는 것을 고려해보세요:
enum class RightIconType { NONE, CHEVRON, PLUS }Also applies to: 74-74
app/src/main/java/com/texthip/thip/ui/common/modal/InfoPopup.kt (1)
96-97: 하드코딩된 문자열을 StringResource로 추출하세요."닫기" 문자열이 하드코딩되어 있습니다. 이전 학습 내용에 따르면 StringResource 파일로 추출하는 것을 선호하신다고 했으니, 이를
strings.xml로 이동하는 것이 좋겠습니다.- contentDescription = "닫기", + contentDescription = stringResource(R.string.close),app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt (1)
147-148: 프리뷰 함수 이름의 일관성을 개선하세요.프리뷰 함수 이름이
GroupRecruitingScreenPreview로 되어 있지만, 실제 컴포넌트 이름은BookRecruitingScreen입니다. 일관성을 위해BookRecruitingScreenPreview로 변경하는 것이 좋겠습니다.-fun GroupRecruitingScreenPreview() { +fun BookRecruitingScreenPreview() {225번째 줄의
GroupRecruitingScreenEmptyPreview도 마찬가지로 변경하세요.app/src/main/java/com/texthip/thip/ui/booksearch/component/BookRecentSearch.kt (2)
115-132: LazyColumn 구현 방식을 개선하세요.현재
items(popularBooks.size)를 사용하고 있지만,itemsIndexed(popularBooks)를 사용하는 것이 더 관용적이고 안전합니다.- items(popularBooks.size) { index -> - val book = popularBooks[index] + itemsIndexed(popularBooks) { index, book ->
129-129: 테마 사용 일관성을 개선하세요.대부분의 곳에서
colors.DarkGrey02를 사용하고 있지만, 여기서는ThipTheme.colors.DarkGrey02를 사용하고 있습니다. 일관성을 위해colors.DarkGrey02로 변경하는 것이 좋겠습니다.- .background(ThipTheme.colors.DarkGrey02) + .background(colors.DarkGrey02)app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupSearchScreen.kt (1)
86-91: 정렬 로직 개선 제안현재 정렬 로직이 명확하지만, 향후 정렬 옵션 추가를 고려하여 enum이나 sealed class를 사용하는 것이 더 확장성 있을 수 있습니다.
enum class SortOption { DEADLINE_SOON, MOST_POPULAR }app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookDetailScreen.kt (2)
92-122: 성능 최적화 고려사항여러 blur 효과와 복잡한 gradient가 사용되고 있어 저사양 기기에서 성능 이슈가 발생할 수 있습니다. 필요시 성능 프로파일링을 통해 최적화를 고려해보세요.
293-294: TODO 주석 처리 필요피드 UI 구현에 대한 TODO가 있습니다. 이슈 트래킹 시스템에 등록하여 관리하는 것이 좋습니다.
이 TODO를 위한 이슈를 생성하시겠습니까?
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookSearchScreen.kt (2)
122-122: 서버 연동 TODO 처리 필요인기 도서 날짜를 서버에서 받아오도록 구현이 필요합니다.
이 TODO를 위한 이슈를 생성하거나 구현을 도와드릴까요?
51-74: 필터링 로직 중복 제거 가능
liveFilteredBookList와filteredBookList의 필터링 로직이 중복되어 있습니다. 공통 함수로 추출하면 유지보수성이 향상됩니다.private fun List<BookData>.filterBySearchText(searchText: String): List<BookData> { return if (searchText.isBlank()) emptyList() else filter { book -> book.title.contains(searchText, ignoreCase = true) || book.author.contains(searchText, ignoreCase = true) || book.publisher.contains(searchText, ignoreCase = true) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
.idea/misc.xml(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/component/BookEmptyResult.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/component/BookFilteredSearchResult.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/component/BookLiveSearchResult.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/component/BookRecentSearch.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/mock/BookData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/mock/DetailBookData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookDetailScreen.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookSearchScreen.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/common/buttons/ActionMediumButton.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/common/cards/CardBookSearch.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/common/modal/InfoPopup.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/common/screen/RegisterBookScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyResult.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupFilteredSearchResult.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupLiveSearchResult.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupRecentSearch.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomSecretScreen.kt(0 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupSearchScreen.kt(5 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt(0 hunks)app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt(1 hunks)app/src/main/res/values/strings.xml(1 hunks)
💤 Files with no reviewable changes (2)
- app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt
- app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomSecretScreen.kt
🧰 Additional context used
🧠 Learnings (6)
📓 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/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/group/myroom/screen/GroupRoomScreen.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/myroom/component/GroupRecentSearch.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/common/modal/InfoPopup.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/myroom/screen/GroupSearchScreen.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 (6)
app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt (1)
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookSearchScreen.kt (1)
BookSearchScreen(36-160)
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookLiveSearchResult.kt (1)
app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt (1)
CardBookList(37-104)
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookEmptyResult.kt (1)
app/src/main/java/com/texthip/thip/ui/common/buttons/ActionMediumButton.kt (1)
ActionMediumButton(31-80)
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookFilteredSearchResult.kt (3)
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookEmptyResult.kt (1)
BookEmptyResult(21-55)app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt (1)
CardBookList(37-104)app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
ThipTheme(41-69)
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookRecentSearch.kt (3)
app/src/main/java/com/texthip/thip/ui/common/buttons/GenreChipButton.kt (1)
GenreChipButton(28-70)app/src/main/java/com/texthip/thip/ui/common/cards/CardBookSearch.kt (1)
CardBookSearch(28-76)app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
ThipTheme(41-69)
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupFilteredSearchResult.kt (1)
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyResult.kt (1)
GroupEmptyResult(16-38)
🔇 Additional comments (31)
.idea/misc.xml (1)
7-7: IDE 설정 변경 승인프로젝트 JDK 설정을 기본값으로 명시적으로 표시하는 표준 IDE 설정 변경입니다.
app/src/main/java/com/texthip/thip/ui/booksearch/mock/BookData.kt (1)
5-10: 데이터 클래스 구조 양호기본 도서 정보를 담는 데이터 클래스가 잘 구성되어 있습니다. mock 패키지에 위치한 것으로 보아 개발/테스트용으로 보이며, 프로덕션 환경에서는 실제 서버 응답에 맞는 구조로 확장이 필요할 것 같습니다.
app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt (1)
17-17: 명시적 매개변수 전달 개선매개변수 이름을 명시적으로 지정하여 코드의 가독성과 명확성을 향상시켰습니다.
app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt (1)
373-373: 코드 간소화 개선불필요한 지역 변수를 제거하고 직접
colors.Purple을 사용하여 코드를 간소화했습니다. 가독성과 유지보수성이 향상되었습니다.app/src/main/java/com/texthip/thip/ui/common/screen/RegisterBookScreen.kt (1)
1-1: 패키지 이동과 함수명 변경이 적절합니다.공통 화면으로 이동하여 재사용성을 높이고, 함수명을 단순화한 것이 좋습니다. 모든 문자열이 string resource로 적절히 추출되어 있어 현지화 대응도 잘 되어 있습니다.
Also applies to: 22-22
app/src/main/res/values/strings.xml (1)
258-282: 책 검색 기능에 대한 문자열 리소스가 잘 구성되어 있습니다.새로운 책 검색 및 모집 기능을 위한 문자열 리소스가 체계적으로 추가되었습니다. 주석을 통한 구분과 일관된 네이밍 컨벤션이 좋습니다. 이는 사용자가 선호하는 방식으로 하드코딩된 문자열을 리소스 파일로 추출하는 모범 사례입니다.
app/src/main/java/com/texthip/thip/ui/booksearch/component/BookLiveSearchResult.kt (1)
18-43: 책 검색 결과 리스트 컴포넌트가 잘 구현되었습니다.기존
CardBookList컴포넌트를 재사용하여 일관성을 유지하고, 마지막 아이템을 제외한 구분선 처리가 올바르게 구현되어 있습니다. LazyColumn을 사용한 성능 최적화도 적절합니다.app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupRecentSearch.kt (2)
1-1: 컴포넌트 구조 개선이 적절합니다.패키지를
component로 이동하고 함수명을 단순화한 것이 좋습니다. 특히colors와typography임포트를 함수 내부에서 최상위로 이동한 것은 코드 구조를 개선합니다.Also applies to: 15-16, 19-19
24-51: 최근 검색어 처리 로직이 잘 구현되어 있습니다.빈 상태와 검색어가 있는 상태를 적절히 처리하고, 최대 9개까지 표시하는 제한도 합리적입니다. 모든 문자열이 string resource로 추출되어 있어 현지화 대응도 완벽합니다.
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyResult.kt (3)
1-1: 패키지 구조 개선이 잘 되었습니다.
screen에서component로 패키지를 변경한 것이 적절합니다. 이 컴포저블은 재사용 가능한 컴포넌트의 성격을 가지므로 더 정확한 분류입니다.
17-17: 함수명 변경이 적절합니다.
GroupEmptyResultScreen에서GroupEmptyResult로 변경하여 "Screen" 접미사를 제거한 것이 좋습니다. 이는 재사용 가능한 컴포넌트의 특성을 더 잘 반영합니다.
13-14: 테마 임포트 구조 개선이 좋습니다.
ThipTheme.colors와ThipTheme.typography를 상단에서 임포트하여 함수 내부에서 직접 사용할 수 있도록 한 것이 코드 가독성을 향상시킵니다.app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupLiveSearchResult.kt (2)
1-1: 일관된 패키지 구조 개선입니다.다른 컴포넌트들과 동일하게
component패키지로 이동한 것이 일관성 있는 리팩토링입니다.
9-9: 리스트 렌더링 개선이 우수합니다.
items에서itemsIndexed로 변경하고 조건부 구분선을 추가한 것이 좋습니다. 마지막 아이템 뒤에 불필요한 구분선이 표시되는 것을 방지합니다.if (index < roomList.size - 1) { Spacer(/* divider */) }이 패턴은 UI 일관성을 향상시키는 좋은 접근입니다.
Also applies to: 24-42
app/src/main/java/com/texthip/thip/ui/common/cards/CardBookSearch.kt (3)
31-31: 선택적 번호 매개변수 추가가 적절합니다.
number: Int? = null로 선택적 매개변수를 추가하여 기존 코드의 호환성을 유지하면서 새로운 기능을 제공합니다.
42-49: 번호 표시 구현이 깔끔합니다.
number?.let구문을 사용하여 null 안전성을 보장하고, 적절한 포맷팅("$it. ")과 스타일링을 적용했습니다. 패딩도 적절히 설정되어 있습니다.
87-87: 프리뷰 업데이트가 적절합니다.새로운
number매개변수를 프리뷰에 추가하여 기능을 시연할 수 있도록 한 것이 좋습니다.app/src/main/java/com/texthip/thip/ui/booksearch/mock/DetailBookData.kt (1)
5-13: 데이터 클래스 설계가 잘 되었습니다.상세 책 정보에 필요한 모든 필드를 포함하고, 합리적인 기본값을 제공합니다. 특히
coverImageRes에 대한 nullable 처리와 기본 샘플 이미지 설정이 적절합니다.app/src/main/java/com/texthip/thip/ui/booksearch/component/BookEmptyResult.kt (3)
22-26: 컴포저블 함수 시그니처가 적절합니다.
mainText와subText를 매개변수로 받아 재사용성을 높인 것이 좋습니다. 콜백 함수도 명확하게 정의되어 있습니다.
27-42: 레이아웃 구조가 잘 설계되었습니다.중앙 정렬된
Column을 사용하고, 적절한 스페이싱과 테마 색상/타이포그래피를 적용했습니다. 텍스트 계층 구조도 명확합니다.
45-53: ActionMediumButton 기본 높이·너비 일관성 검토 필요
ActionMediumButton구현부에서 기본 높이를.height(44.dp)로 고정하고, 너비를 별도 지정하지 않으면.fillMaxWidth()가 적용됩니다.
현재 빈 결과 화면에서는 너비를.width(97.dp)로 고정하고 있는데, 디자인 가이드상 해당 버튼의 폭이 97.dp로 명시되어 있는지 확인 부탁드립니다.검토 대상 위치:
- app/src/main/java/com/texthip/thip/ui/booksearch/component/BookEmptyResult.kt
· ActionMediumButton(modifier = Modifier.width(97.dp))- app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupEmptyBookSheetContent.kt
· ActionMediumButton(modifier = Modifier.width(97.dp))- app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt
· ActionMediumButton(modifier = Modifier.weight(1f))- app/src/main/java/com/texthip/thip/ui/signin/screen/LoginScreen.kt
· ActionMediumButton(기본 fillMaxWidth())- app/src/main/java/com/texthip/thip/ui/signin/screen/SignupDoneScreen.kt
· ActionMediumButton(modifier = Modifier.width(180.dp))app/src/main/java/com/texthip/thip/ui/booksearch/component/BookFilteredSearchResult.kt (2)
21-75: 컴포넌트 구조가 잘 구성되어 있습니다.깔끔한 구조로 검색 결과를 표시하는 컴포넌트가 구현되었습니다. 빈 상태 처리와 리스트 렌더링이 적절하게 구현되어 있습니다.
52-72: LazyColumn 구현이 효율적입니다.
itemsIndexed를 사용하여 마지막 아이템 이후에 구분선이 나타나지 않도록 한 것이 좋습니다. 이는 UI 일관성을 높이는 좋은 접근 방식입니다.app/src/main/java/com/texthip/thip/ui/common/modal/InfoPopup.kt (1)
40-103: 모달 구조 개선이 잘 되었습니다.레이아웃 계층 구조가 더 명확해졌고, 닫기 버튼 추가로 사용자 경험이 개선되었습니다. 스크롤 기능도 적절히 구현되어 있습니다.
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt (2)
42-44: 필터링 로직이 효율적으로 구현되었습니다.
remember를 사용하여allDataList가 변경될 때만 필터링이 다시 수행되도록 최적화한 것이 좋습니다.
81-122: 빈 상태와 리스트 상태 처리가 잘 구현되었습니다.조건부 렌더링을 통해 빈 상태와 리스트 상태를 적절히 처리하고 있으며, 하단 버튼과의 간격도 적절히 고려되었습니다.
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupFilteredSearchResult.kt (3)
1-1: 패키지 구조 개선이 적절합니다.
screen에서component로 패키지를 변경한 것은 컴포넌트의 재사용성을 높이는 좋은 변경입니다.
64-82: LazyColumn의 구분선 로직이 개선되었습니다.
itemsIndexed를 사용하여 마지막 아이템 이후에 구분선이 나타나지 않도록 처리한 것이 UI 일관성을 높이는 좋은 개선입니다.
18-19: 테마 사용 방식이 간소화되었습니다.지역 변수를 제거하고 직접
ThipTheme.colors와ThipTheme.typography를 사용하도록 변경한 것이 더 간결하고 일관적입니다.app/src/main/java/com/texthip/thip/ui/booksearch/component/BookRecentSearch.kt (2)
54-66: FlowRow를 사용한 검색어 칩 구현이 훌륭합니다.
take(9)를 사용하여 최대 9개의 검색어만 표시하고,maxLines = 2로 레이아웃을 제한한 것이 좋은 UX 고려사항입니다.
47-67: 빈 상태 처리가 잘 구현되었습니다.최근 검색어와 인기 도서 모두에 대해 빈 상태를 적절히 처리하고 있으며, 사용자에게 명확한 피드백을 제공하고 있습니다.
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt
Outdated
Show resolved
Hide resolved
| var recentSearches by rememberSaveable { | ||
| mutableStateOf(listOf("user.02", "ㅇㅇ", "훽후ㅣㅣ", "검색4", "검색5", "검색6")) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
하드코딩된 문자열을 StringResource로 추출 필요
recentSearches의 초기값으로 하드코딩된 문자열들이 사용되고 있습니다. 유지보수성과 국제화를 위해 StringResource로 추출하는 것이 좋습니다.
- var recentSearches by rememberSaveable {
- mutableStateOf(listOf("user.02", "ㅇㅇ", "훽후ㅣㅣ", "검색4", "검색5", "검색6"))
- }
+ var recentSearches by rememberSaveable {
+ mutableStateOf(emptyList<String>())
+ }Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupSearchScreen.kt
around lines 43 to 45, the recentSearches list is initialized with hardcoded
strings. To improve maintainability and support internationalization, replace
these hardcoded strings by referencing string resources. Define the strings in
the appropriate strings.xml file and load them using the stringResource function
or equivalent in Compose, then initialize recentSearches with these
resource-based strings.
| LaunchedEffect(Unit) { | ||
| isAlarmVisible = true | ||
| delay(5000) | ||
| isAlarmVisible = false | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
하드코딩된 지연 시간을 상수로 추출
알림 표시 시간이 하드코딩되어 있습니다. 유지보수성을 위해 상수로 추출하는 것이 좋습니다.
파일 상단에 companion object 추가:
companion object {
private const val ALARM_DISPLAY_DURATION = 5000L
}그리고 사용 부분 수정:
- delay(5000)
+ delay(ALARM_DISPLAY_DURATION)🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookDetailScreen.kt
around lines 73 to 77, the delay time of 5000 milliseconds is hardcoded. To
improve maintainability, extract this value into a constant by adding a
companion object at the top of the file with a private constant
ALARM_DISPLAY_DURATION set to 5000L, then replace the hardcoded delay(5000) call
with delay(ALARM_DISPLAY_DURATION).
| var recentSearches by rememberSaveable { | ||
| mutableStateOf(listOf("asd", "qwe", "xcv", "dfggfd", "asdasd", "gfhjghj")) | ||
| } |
There was a problem hiding this comment.
하드코딩된 검색어를 제거하거나 의미있는 값으로 변경
테스트용으로 보이는 하드코딩된 검색어들("asd", "qwe" 등)이 있습니다. 실제 배포 시에는 빈 리스트로 시작하거나 의미있는 초기값을 사용해야 합니다.
- var recentSearches by rememberSaveable {
- mutableStateOf(listOf("asd", "qwe", "xcv", "dfggfd", "asdasd", "gfhjghj"))
- }
+ var recentSearches by rememberSaveable {
+ mutableStateOf(emptyList<String>())
+ }📝 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.
| var recentSearches by rememberSaveable { | |
| mutableStateOf(listOf("asd", "qwe", "xcv", "dfggfd", "asdasd", "gfhjghj")) | |
| } | |
| var recentSearches by rememberSaveable { | |
| mutableStateOf(emptyList<String>()) | |
| } |
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookSearchScreen.kt
around lines 43 to 45, the recentSearches list is initialized with hardcoded
test strings. Replace these test strings with either an empty list or meaningful
initial values appropriate for production to avoid exposing test data in the
deployed app.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt (1)
63-67: 이전 리뷰 댓글과 일치하는 개선사항이 확인됩니다.현재 코드에서
recruitingList.size를 올바르게 사용하고 있어 모집 중인 방의 정확한 개수를 표시하고 있습니다. 이는 이전 리뷰에서 제안된 수정사항이 반영된 것으로 보입니다.
🧹 Nitpick comments (2)
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt (2)
122-139: 하단 버튼의 접근성을 개선할 수 있습니다.Button( colors = ButtonDefaults.buttonColors( containerColor = colors.Purple ), modifier = Modifier .align(Alignment.BottomCenter) .fillMaxWidth() .height(50.dp), shape = RoundedCornerShape(0.dp), - onClick = onCreateRoomClick + onClick = onCreateRoomClick, + contentDescription = stringResource(R.string.group_recruiting_create_button) ) {하지만 Button 컴포넌트는 기본적으로 접근성이 지원되므로, 현재 구현도 충분합니다.
142-217: 프리뷰 함수들이 다양한 상태를 잘 보여줍니다.데이터가 있는 상태와 빈 상태를 모두 프리뷰로 제공하여 개발 중 UI 확인이 용이하도록 구성되어 있습니다. 하지만 프리뷰 함수명이
GroupRecruitingScreenPreview로 되어 있는데, 실제 컴포넌트명은BookRecruitingScreen입니다.@Preview() @Composable -fun GroupRecruitingScreenPreview() { +fun BookRecruitingScreenPreview() { ThipTheme { val dataList = listOf( // ... 데이터 리스트 ) BookRecruitingScreen( recruitingList = dataList ) } } @Preview() @Composable -fun GroupRecruitingScreenEmptyPreview() { +fun BookRecruitingScreenEmptyPreview() { ThipTheme { BookRecruitingScreen( recruitingList = emptyList() ) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 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.
🔇 Additional comments (4)
app/src/main/java/com/texthip/thip/ui/booksearch/screen/BookRecruitingScreen.kt (4)
1-35: 임포트 구문이 깔끔하게 정리되어 있습니다.필요한 Compose 컴포넌트들과 테마 관련 임포트가 적절히 구성되어 있습니다.
36-51: 컴포넌트 시그니처와 상단 앱바 구현이 좋습니다.함수 파라미터가 명확하고 기본값이 적절히 설정되어 있으며, 상단 앱바의 제목이 문자열 리소스를 사용하고 있어 현지화 관점에서 우수합니다.
77-98: 빈 상태 처리가 잘 구현되어 있습니다.모집 중인 방이 없을 때의 빈 상태 UI가 적절히 구현되어 있고, 메인 메시지와 서브 메시지가 명확하게 분리되어 있습니다. 문자열 리소스 사용도 일관성 있게 적용되어 있습니다.
100-117: LazyColumn 구현이 효율적입니다.리스트 렌더링이 적절한 간격과 하단 패딩을 가지고 있으며, 각 아이템의 클릭 콜백이 올바르게 전달되고 있습니다.
There was a problem hiding this comment.
모달의 경우에는 아래의 X 버튼을 추가해야 하고, 텍스트가 가득 찰 경우 오른쪽의 스크롤 바와 텍스트가 붙어있는 문제가 있어서 패딩을 추가했습니다 (이 화면에서만 사용)
There was a problem hiding this comment.
Pull Request Overview
This PR implements the book search screen UI functionality, adding comprehensive search features including real-time search, recent searches, popular books display, and detailed book views. The implementation also includes supporting group recruitment screens and various UI enhancements.
Key Changes
- Complete book search screen implementation with live search, recent searches, and popular books functionality
- Book detail screen with feed integration preparation and recruitment group access
- Group recruitment screen for book-related meeting rooms
- Enhanced UI components including improved buttons, cards, and modal popups
Reviewed Changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/main/res/values/strings.xml | Added string resources for book search, group filtering, and recruitment features |
| app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt | Updated navigation parameter formatting for BookSearchScreen |
| app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt | Removed unused imports and cleaned up code structure |
| app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupSearchScreen.kt | Enhanced search functionality with improved filtering and component refactoring |
| app/src/main/java/com/texthip/thip/ui/group/myroom/component/* | Moved and refactored group search components with improved package structure |
| app/src/main/java/com/texthip/thip/ui/common/screen/RegisterBookScreen.kt | Moved and renamed book registration screen to common package |
| app/src/main/java/com/texthip/thip/ui/common/modal/InfoPopup.kt | Enhanced popup with circular close button and improved layout |
| app/src/main/java/com/texthip/thip/ui/common/cards/* | Enhanced book search cards and removed bookmark functionality from book lists |
| app/src/main/java/com/texthip/thip/ui/common/buttons/ActionMediumButton.kt | Added support for plus icon in action buttons |
| app/src/main/java/com/texthip/thip/ui/booksearch/screen/* | Implemented comprehensive book search, detail, and recruitment screens |
| app/src/main/java/com/texthip/thip/ui/booksearch/mock/* | Added book data models for search functionality |
| app/src/main/java/com/texthip/thip/ui/booksearch/component/* | Implemented book search components for different search states |
Files not reviewed (1)
- .idea/misc.xml: Language not supported
| Spacer(modifier = Modifier.width(12.dp)) | ||
|
|
||
| IconButton( | ||
| // 북마크 아이콘 제거(쓰는 화면이 안보임) |
There was a problem hiding this comment.
Instead of commenting out the bookmark functionality, consider removing the dead code entirely or using a feature flag if this functionality might be restored later.
| .height(1.dp) | ||
| .background(colors.DarkGrey02) | ||
| ) | ||
| if (index < roomList.size - 1) { |
There was a problem hiding this comment.
The spacer logic should be moved outside the itemsIndexed block to avoid conditional rendering inside compose items, which can cause performance issues.
| .height(1.dp) | ||
| .background(colors.DarkGrey02) | ||
| ) | ||
| if (index < roomList.size - 1) { |
There was a problem hiding this comment.
The spacer logic should be moved outside the itemsIndexed block to avoid conditional rendering inside compose items, which can cause performance issues.
| items(popularBooks.size) { index -> | ||
| val book = popularBooks[index] | ||
| CardBookSearch( | ||
| number = index + 1, | ||
| title = book.title, | ||
| imageRes = book.imageRes, | ||
| onClick = { onBookClick(book) } | ||
| ) | ||
| if (index < popularBooks.size - 1) { |
There was a problem hiding this comment.
The spacer logic should be moved outside the items block to avoid conditional rendering inside compose items, which can cause performance issues.
| items(popularBooks.size) { index -> | |
| val book = popularBooks[index] | |
| CardBookSearch( | |
| number = index + 1, | |
| title = book.title, | |
| imageRes = book.imageRes, | |
| onClick = { onBookClick(book) } | |
| ) | |
| if (index < popularBooks.size - 1) { | |
| val itemsWithSpacers = popularBooks.flatMapIndexed { index, book -> | |
| if (index < popularBooks.size - 1) { | |
| listOf(book, null) // null represents a Spacer | |
| } else { | |
| listOf(book) | |
| } | |
| } | |
| items(itemsWithSpacers.size) { index -> | |
| val item = itemsWithSpacers[index] | |
| if (item != null) { | |
| val book = item | |
| CardBookSearch( | |
| number = index / 2 + 1, // Adjusted for interleaved list | |
| title = book.title, | |
| imageRes = book.imageRes, | |
| onClick = { onBookClick(book) } | |
| ) | |
| } else { |
| itemsIndexed(bookList) { index, book -> | ||
| CardBookList( | ||
| title = book.title, | ||
| author = book.author, | ||
| publisher = book.publisher, | ||
| imageRes = book.imageRes | ||
| ) | ||
| if (index < bookList.size - 1) { |
There was a problem hiding this comment.
The spacer logic should be moved outside the itemsIndexed block to avoid conditional rendering inside compose items, which can cause performance issues.
| itemsIndexed(bookList) { index, book -> | |
| CardBookList( | |
| title = book.title, | |
| author = book.author, | |
| publisher = book.publisher, | |
| imageRes = book.imageRes | |
| ) | |
| if (index < bookList.size - 1) { | |
| items(bookList.flatMapIndexed { index, book -> | |
| if (index < bookList.size - 1) { | |
| listOf(book, null) // Add a null to represent a spacer | |
| } else { | |
| listOf(book) // No spacer after the last item | |
| } | |
| }) { item -> | |
| if (item != null) { | |
| CardBookList( | |
| title = item.title, | |
| author = item.author, | |
| publisher = item.publisher, | |
| imageRes = item.imageRes | |
| ) | |
| } else { |
| CardBookList( | ||
| title = book.title, | ||
| author = book.author, | ||
| publisher = book.publisher, | ||
| imageRes = book.imageRes | ||
| ) | ||
| if (index < bookList.size - 1) { | ||
| Spacer( | ||
| modifier = Modifier | ||
| .padding(top = 12.dp, bottom = 12.dp) | ||
| .fillMaxWidth() | ||
| .height(1.dp) | ||
| .background(colors.DarkGrey02) | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
The spacer logic should be moved outside the itemsIndexed block to avoid conditional rendering inside compose items, which can cause performance issues.
| CardBookList( | |
| title = book.title, | |
| author = book.author, | |
| publisher = book.publisher, | |
| imageRes = book.imageRes | |
| ) | |
| if (index < bookList.size - 1) { | |
| Spacer( | |
| modifier = Modifier | |
| .padding(top = 12.dp, bottom = 12.dp) | |
| .fillMaxWidth() | |
| .height(1.dp) | |
| .background(colors.DarkGrey02) | |
| ) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| BookListItem( | |
| book = book, | |
| showSpacer = index < bookList.size - 1 | |
| ) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| @Composable | |
| fun BookListItem( | |
| book: BookData, | |
| showSpacer: Boolean | |
| ) { | |
| Column { | |
| CardBookList( | |
| title = book.title, | |
| author = book.author, | |
| publisher = book.publisher, | |
| imageRes = book.imageRes | |
| ) | |
| if (showSpacer) { | |
| Spacer( | |
| modifier = Modifier | |
| .padding(top = 12.dp, bottom = 12.dp) | |
| .fillMaxWidth() | |
| .height(1.dp) | |
| .background(colors.DarkGrey02) | |
| ) | |
| } | |
| } | |
| } |
| popularBooks: List<BookData> = emptyList() | ||
| ) { | ||
| var recentSearches by rememberSaveable { | ||
| mutableStateOf(listOf("asd", "qwe", "xcv", "dfggfd", "asdasd", "gfhjghj")) |
There was a problem hiding this comment.
Replace placeholder search terms with more meaningful examples or empty list for production code.
| mutableStateOf(listOf("asd", "qwe", "xcv", "dfggfd", "asdasd", "gfhjghj")) | |
| mutableStateOf(emptyList<String>()) |
| } | ||
| } | ||
| } else { | ||
| // TODO: 피드 UI 구현 되면 수정 |
There was a problem hiding this comment.
Add a ticket reference or more specific details about the planned feed UI implementation to improve task tracking.
| // TODO: 피드 UI 구현 되면 수정 | |
| // TODO: Implement feed UI. Refer to ticket #FEED-123 for design and requirements. |
➕ 이슈 링크
🔎 작업 내용
📸 스크린샷
** 책 검색 페이지 화면 구현**
https://github.com/user-attachments/assets/10499764-d302-43bd-b116-e66433c7637d
책 상세 페이지 화면 구현
https://github.com/user-attachments/assets/29810011-d262-4f4e-bf55-4c16d1f62931
모집중인 모임방 구현


😢 해결하지 못한 과제
책 상세 페이지의 경우 아직 피드 UI와 연결하지 못했습니다
📢 리뷰어들에게
Summary by CodeRabbit
새로운 기능
버그 수정
리팩터링/스타일
문서 및 번역
기타