feat: 홈화면 UI 개편#212
Hidden character warning
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GET /api/v1/home/popular-collections 엔드포인트 추가 - PopularCollectionResponseDto 신규 생성 및 CollectionListModel 매퍼 추가 - HomeViewModel recentCollection → popularCollection 교체, CollectionRepository 의존성 제거 - CollectionListViewModel FAMOUS 라우트 popular API로 교체 - TokenInterceptor에서 /api/v1/search/contents 요청 시 토큰 헤더 제외 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts: # app/src/main/java/com/flint/data/di/interceptor/TokenInterceptor.kt
- /api/v1/contents/bookmarks(ContentRepository) → GET /api/v1/users/me/bookmarked-collections(UserRepository)
- HomeViewModel: ContentRepository 제거, UserRepository 주입, getBookmarkedCollectionList()로 변경
- HomeUiState: bookmarkedContentListLoadState → bookmarkedCollectionListLoadState(CollectionListModel)
- HomeScreen: SavedContentsSection → CollectionSection("저장한 컬렉션"), OTT 바텀시트 제거
- 저장 컬렉션 클릭 시 컬렉션 상세 화면으로 이동
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- UserApi: /api/v1/contents/{userId} → /api/v1/users/{userId}/bookmarked-contents 경로 수정
- BookmarkedContentListResponseDto: totalCount, bookmarkCount, isBookmarked 필드 추가
- HomeViewModel: getUserBookmarkedContents(null) 호출, OTT 바텀시트 복구
- HomeUiState: bookmarkedContentListLoadState(BookmarkedContentListModel) 복구
- HomeScreen: SavedContentsSection 복구, 아이템 0개일 때 섹션 숨김
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
스크롤 가능한 콘텐츠가 있음을 암시하는 하단 페이드 오버레이 추가 (투명 → 배경색, 80dp) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthrough홈 화면을 "최근 컬렉션" 기반에서 "인기 컬렉션" 기반으로 전환한다. Popular Collections API 스택(DTO → Mapper → Repository → ViewModel)을 신규 구축하고, 추천 컬렉션 무한 페이저 컴포넌트( Changes홈 인기 컬렉션 피처 및 화면 재구성
Sequence Diagram(s)sequenceDiagram
participant HomeRoute
participant HomeViewModel
participant HomeRepository
participant HomeApi
rect rgba(100, 149, 237, 0.5)
Note over HomeRoute,HomeViewModel: 초기 로딩
HomeRoute->>HomeViewModel: getRecommendedCollectionList()
HomeRoute->>HomeViewModel: getBookmarkedContentList() via userRepository
HomeRoute->>HomeViewModel: getPopularCollectionList()
end
HomeViewModel->>HomeRepository: getPopularCollectionList()
HomeRepository->>HomeApi: GET /api/v1/home/popular-collections
HomeApi-->>HomeRepository: PopularCollectionResponseDto
HomeRepository-->>HomeViewModel: Result<CollectionListModel>
HomeViewModel-->>HomeRoute: popularCollectionListLoadState → Success
HomeRoute->>HomeRoute: HomeScreen(famousCollectionModelList=...)
sequenceDiagram
participant User
participant HomeScreen
participant HomeRecommendCollectionList
participant RecommendCollectionCard
participant CollectionSection
User->>HomeScreen: 화면 진입
HomeScreen->>HomeRecommendCollectionList: collectionListModel (recommended)
HomeRecommendCollectionList->>RecommendCollectionCard: item, isCurrentPage
RecommendCollectionCard-->>User: 그라데이션 카드 렌더링
HomeScreen->>CollectionSection: famousCollectionModelList (인기 컬렉션)
CollectionSection-->>User: 인기 컬렉션 그리드 렌더링
User->>RecommendCollectionCard: 카드 클릭
RecommendCollectionCard->>HomeScreen: onFamousCollectionItemClick(id)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 2
🤖 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
`@app/src/main/java/com/flint/data/dto/content/response/BookmarkedContentListResponseDto.kt`:
- Around line 8-9: The new fields totalCount in BookmarkedContentListResponseDto
and bookmarkCount and isBookmarked in BookmarkedContentResponseDto are added to
the DTOs but not being mapped to the domain models. Update the toModel()
extension functions in ContentMapper.kt for both
BookmarkedContentListResponseDto (lines 13-28) and BookmarkedContentResponseDto
to include mappings for totalCount, bookmarkCount, and isBookmarked
respectively. Additionally, add these corresponding fields to the domain model
classes BookmarkedContentListModel and BookmarkedContentItemModel so the API
response data is properly preserved through the mapping layer instead of being
discarded.
In `@app/src/main/java/com/flint/presentation/home/HomeViewModel.kt`:
- Around line 66-82: In the three functions getRecommendedCollectionList,
getBookmarkedContentList, and getPopularCollectionList, the onFailure blocks
only log errors but do not emit failure states to the UI. For each function,
replace the onFailure block that currently calls Timber.e(it.message) with code
that emits a UiState.Failure state to the corresponding MutableStateFlow: emit
UiState.Failure to _recommendCollectionListLoadState in
getRecommendedCollectionList, emit UiState.Failure to
_bookmarkedContentListLoadState in getBookmarkedContentList, and emit
UiState.Failure to _popularCollectionListLoadState in getPopularCollectionList.
Include the error details in each UiState.Failure emission so the UI can
properly handle and display error states instead of remaining stuck in a Loading
state.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1585074e-0333-48f8-bd72-7e25e28e4948
⛔ Files ignored due to path filters (1)
app/src/main/res/drawable/img_home_banner.pngis excluded by!**/*.png
📒 Files selected for processing (21)
app/src/main/java/com/flint/core/designsystem/component/bottomsheet/OttListBottomSheet.ktapp/src/main/java/com/flint/core/designsystem/component/listItem/OttShortCutListItem.ktapp/src/main/java/com/flint/core/designsystem/theme/Color.ktapp/src/main/java/com/flint/core/navigation/model/CollectionListRouteType.ktapp/src/main/java/com/flint/data/api/HomeApi.ktapp/src/main/java/com/flint/data/api/UserApi.ktapp/src/main/java/com/flint/data/di/interceptor/TokenInterceptor.ktapp/src/main/java/com/flint/data/dto/content/response/BookmarkedContentListResponseDto.ktapp/src/main/java/com/flint/data/dto/home/response/PopularCollectionResponseDto.ktapp/src/main/java/com/flint/domain/mapper/collection/CollectionMapper.ktapp/src/main/java/com/flint/domain/model/collection/CollectionListModel.ktapp/src/main/java/com/flint/domain/repository/HomeRepository.ktapp/src/main/java/com/flint/presentation/collectionlist/CollectionListScreen.ktapp/src/main/java/com/flint/presentation/collectionlist/CollectionListViewModel.ktapp/src/main/java/com/flint/presentation/home/HomeScreen.ktapp/src/main/java/com/flint/presentation/home/HomeViewModel.ktapp/src/main/java/com/flint/presentation/home/component/HomeBanner.ktapp/src/main/java/com/flint/presentation/home/component/HomeRecommendCollectionList.ktapp/src/main/java/com/flint/presentation/home/component/RecommendCollectionCard.ktapp/src/main/java/com/flint/presentation/home/uistate/HomeUiState.ktapp/src/main/java/com/flint/presentation/profile/ProfileScreen.kt
💤 Files with no reviewable changes (1)
- app/src/main/java/com/flint/presentation/profile/ProfileScreen.kt
| @SerialName("totalCount") | ||
| val totalCount: Int = 0, |
There was a problem hiding this comment.
DTO에 추가된 필드가 도메인 모델로 매핑되지 않음.
BookmarkedContentListResponseDto에 totalCount, BookmarkedContentResponseDto에 bookmarkCount와 isBookmarked 필드가 추가되었지만, ContentMapper.kt의 toModel() 확장 함수에서 이 필드들을 매핑하지 않고 있습니다 (app/src/main/java/com/flint/domain/mapper/content/ContentMapper.kt:13-28 참조).
API가 이제 이 데이터를 제공한다면 도메인 모델과 UI 상태에 반영되어야 합니다. 현재는 API 응답 데이터가 버려지고 있어 데이터 무결성 문제가 발생합니다.
🔧 제안: 매퍼 업데이트
ContentMapper.kt를 업데이트하여 새 필드를 매핑하세요:
fun BookmarkedContentListResponseDto.toModel() : BookmarkedContentListModel {
return BookmarkedContentListModel(
totalCount = totalCount,
contents = contents.map { it.toModel() }.toImmutableList()
)
}
fun BookmarkedContentResponseDto.toModel() : BookmarkedContentItemModel {
return BookmarkedContentItemModel(
id = id,
title = title,
year = year,
imageUrl = imageUrl,
bookmarkCount = bookmarkCount,
isBookmarked = isBookmarked,
getOttSimpleList = getOttSimpleList.mapNotNull { ottSimple ->
runCatching { OttType.valueOf(ottSimple.ottName) }.getOrNull()
}
)
}그리고 BookmarkedContentListModel 및 BookmarkedContentItemModel에도 해당 필드를 추가하세요.
Also applies to: 24-27
🤖 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
`@app/src/main/java/com/flint/data/dto/content/response/BookmarkedContentListResponseDto.kt`
around lines 8 - 9, The new fields totalCount in
BookmarkedContentListResponseDto and bookmarkCount and isBookmarked in
BookmarkedContentResponseDto are added to the DTOs but not being mapped to the
domain models. Update the toModel() extension functions in ContentMapper.kt for
both BookmarkedContentListResponseDto (lines 13-28) and
BookmarkedContentResponseDto to include mappings for totalCount, bookmarkCount,
and isBookmarked respectively. Additionally, add these corresponding fields to
the domain model classes BookmarkedContentListModel and
BookmarkedContentItemModel so the API response data is properly preserved
through the mapping layer instead of being discarded.
| fun getRecommendedCollectionList() = viewModelScope.launch { | ||
| homeRepository.getRecommendedCollectionList() | ||
| .onSuccess { | ||
| _recommendCollectionListLoadState.emit(UiState.Success(it)) | ||
| } | ||
| .onFailure { | ||
| Timber.e(it.message) | ||
| } | ||
| .onSuccess { _recommendCollectionListLoadState.emit(UiState.Success(it)) } | ||
| .onFailure { Timber.e(it.message) } | ||
| } | ||
|
|
||
| fun getBookmarkedContentList() = viewModelScope.launch { | ||
| contentRepository.getBookmarkedContentList() | ||
| .onSuccess { | ||
| _bookmarkedContentListLoadState.emit(UiState.Success(it)) | ||
| } | ||
| .onFailure { | ||
| Timber.e(it.message) | ||
| } | ||
| userRepository.getUserBookmarkedContents(userId = null) | ||
| .onSuccess { _bookmarkedContentListLoadState.emit(UiState.Success(it)) } | ||
| .onFailure { Timber.e(it.message) } | ||
| } | ||
|
|
||
| fun getRecentCollectionList() = viewModelScope.launch { | ||
| collectionRepository.getRecentCollectionList() | ||
| .onSuccess { | ||
| _recentCollectionListLoadState.emit(UiState.Success(it)) | ||
| } | ||
| .onFailure { | ||
| Timber.e(it.message) | ||
| } | ||
| fun getPopularCollectionList() = viewModelScope.launch { | ||
| homeRepository.getPopularCollectionList() | ||
| .onSuccess { _popularCollectionListLoadState.emit(UiState.Success(it)) } | ||
| .onFailure { Timber.e(it.message) } | ||
| } |
There was a problem hiding this comment.
실패 시 UiState.Failure를 emit하지 않아 홈 로딩 상태가 무한 Loading으로 고정됩니다.
Line 69, Line 75, Line 81에서 로그만 남기고 상태를 갱신하지 않아 HomeUiState.loadState의 실패 분기가 사실상 동작하지 않습니다. 각 onFailure에서 대응하는 MutableStateFlow에 실패 상태를 반영해주세요.
수정 예시
fun getRecommendedCollectionList() = viewModelScope.launch {
homeRepository.getRecommendedCollectionList()
.onSuccess { _recommendCollectionListLoadState.emit(UiState.Success(it)) }
- .onFailure { Timber.e(it.message) }
+ .onFailure {
+ _recommendCollectionListLoadState.emit(UiState.Failure)
+ Timber.e(it.message)
+ }
}
fun getBookmarkedContentList() = viewModelScope.launch {
userRepository.getUserBookmarkedContents(userId = null)
.onSuccess { _bookmarkedContentListLoadState.emit(UiState.Success(it)) }
- .onFailure { Timber.e(it.message) }
+ .onFailure {
+ _bookmarkedContentListLoadState.emit(UiState.Failure)
+ Timber.e(it.message)
+ }
}
fun getPopularCollectionList() = viewModelScope.launch {
homeRepository.getPopularCollectionList()
.onSuccess { _popularCollectionListLoadState.emit(UiState.Success(it)) }
- .onFailure { Timber.e(it.message) }
+ .onFailure {
+ _popularCollectionListLoadState.emit(UiState.Failure)
+ Timber.e(it.message)
+ }
}🤖 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 `@app/src/main/java/com/flint/presentation/home/HomeViewModel.kt` around lines
66 - 82, In the three functions getRecommendedCollectionList,
getBookmarkedContentList, and getPopularCollectionList, the onFailure blocks
only log errors but do not emit failure states to the UI. For each function,
replace the onFailure block that currently calls Timber.e(it.message) with code
that emits a UiState.Failure state to the corresponding MutableStateFlow: emit
UiState.Failure to _recommendCollectionListLoadState in
getRecommendedCollectionList, emit UiState.Failure to
_bookmarkedContentListLoadState in getBookmarkedContentList, and emit
UiState.Failure to _popularCollectionListLoadState in getPopularCollectionList.
Include the error details in each UiState.Failure emission so the UI can
properly handle and display error states instead of remaining stuck in a Loading
state.
Summary
Changes
HomeScreen: 인기 컬렉션 섹션 리팩토링, 추천 컬렉션 컴포넌트 분리HomeViewModel: 인기 컬렉션 API 연동, 북마크 컬렉션 API로 교체HomeRecommendCollectionList,RecommendCollectionCard: 신규 추천 컬렉션 UI 컴포넌트CollectionListScreen: 하단 그라데이션 그림자 추가 (148dp)CollectionListRouteType: RECENT → FAMOUS 라우트 타입 변경HomeApi: 인기 컬렉션 엔드포인트 추가, 최근 저장 엔드포인트 교체TokenInterceptor: 검색 공개 엔드포인트 토큰 제외 처리Color.kt: 디자인 시스템 색상 추가Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항