[Feat] CollectionDetailScreen 구현#139
Conversation
# Conflicts: # app/src/main/java/com/flint/core/common/di/interceptor/TokenInterceptor.kt # app/src/main/java/com/flint/data/api/CollectionApi.kt # app/src/main/java/com/flint/domain/repository/CollectionRepository.kt # app/src/main/java/com/flint/presentation/main/MainNavigator.kt
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
📝 WalkthroughWalkthrough컬렉션 북마크 기능을 추가하고 CollectionDetail 화면과 관련 UI/데이터 계층을 CollectionBookmarkUsersModel 및 CollectionDetailModelNew 등의 새 타입으로 마이그레이션했습니다. API, DTO, 매퍼, 리포지토리, ViewModel, 화면, 내비게이션, 토스트/PeopleBottomSheet UI가 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant Screen as CollectionDetailScreen
participant VM as CollectionDetailViewModel
participant Repo as Repository
participant API as RetrofitAPI
participant Mapper as Mapper
participant Model as DomainModel
User->>Screen: 화면 진입
Screen->>VM: 초기 로드 요청 (collectionId from SavedStateHandle)
par 병렬
VM->>Repo: getCollectionDetail(collectionId)
Repo->>API: GET /api/v1/collections/{collectionId}
API-->>Repo: BaseResponse<CollectionDetailResponseDto>
Repo->>Mapper: toModel() -> CollectionDetailModelNew
Mapper-->>Repo: CollectionDetailModelNew
and
VM->>Repo: getCollectionBookmarkUsers(collectionId)
Repo->>API: GET /api/v1/bookmarks/{collectionId}
API-->>Repo: BaseResponse<CollectionBookmarkUsersDto>
Repo->>Mapper: toModel() -> CollectionBookmarkUsersModel
Mapper-->>Repo: CollectionBookmarkUsersModel
end
Repo-->>VM: Results
VM-->>Screen: UiState.Success(CollectionDetailUiState)
User->>Screen: 북마크 토글 클릭
Screen->>VM: toggleCollectionBookmark()
VM->>Repo: toggleCollectionBookmark(collectionId)
Repo->>API: POST /api/v1/bookmarks/collections/{collectionId}
API-->>Repo: BaseResponse<Boolean>
Repo-->>VM: Result<Boolean>
VM-->>Screen: SideEffect (ToggleCollectionBookmarkSuccess/Failure)
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. 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 |
36bd2b1 to
8456760
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt (2)
363-451: 컴파일 에러: Preview Provider 타입 불일치
PeoplePreviewProvider가ImmutableList<AuthorModel>을 반환하지만, Line 456의PeopleWhoSavedThisCollectionPreview는ImmutableList<CollectionBookmarkUsersModel.User>를 기대합니다. 이로 인해 컴파일 에러가 발생합니다.🐛 제안하는 수정 방안
-private class PeoplePreviewProvider : PreviewParameterProvider<ImmutableList<AuthorModel>> { - override val values: Sequence<ImmutableList<AuthorModel>> = +private class PeoplePreviewProvider : PreviewParameterProvider<ImmutableList<CollectionBookmarkUsersModel.User>> { + override val values: Sequence<ImmutableList<CollectionBookmarkUsersModel.User>> = sequenceOf( persistentListOf( - AuthorModel( + CollectionBookmarkUsersModel.User( userId = "1", - nickname = "유저1", - profileUrl = "", + nickName = "유저1", + profileImageUrl = "", userRole = UserRoleType.FLING, ), ), // ... 나머지 항목들도 동일하게 변경 ) }
807-850: 컴파일 에러: ContentPreviewProvider 타입 불일치
ContentPreviewProvider가ContentModel을 반환하지만, Line 850의ContentPreview는ContentModelNew를 기대합니다. 이로 인해 컴파일 에러가 발생합니다.🐛 제안하는 수정 방안
-private class ContentPreviewProvider : PreviewParameterProvider<ContentModel> { - override val values: Sequence<ContentModel> = +private class ContentPreviewProvider : PreviewParameterProvider<ContentModelNew> { + override val values: Sequence<ContentModelNew> = sequenceOf( - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "드라마 제목", year = 2000, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix, OttType.Disney), + imageUrl = "", director = "가스 제닝스", - description = "달라진 온도...", - isSpoiler = false, + reason = "달라진 온도...", isBookmarked = false, + isSpoiler = false, + bookmarkCount = 0, ), // ... 나머지 항목들도 동일하게 변경 ) }
🤖 Fix all issues with AI agents
In `@app/src/main/java/com/flint/data/api/BookmarkApi.kt`:
- Around line 11-20: The two Retrofit endpoints use inconsistent path formats:
getCollectionBookmarkUsers uses "/api/v1/..." (leading slash) while
toggleCollectionBookmark uses "api/v1/..." (no leading slash); update the path
in toggleCollectionBookmark to include the leading slash (change
`@POST`("api/v1/bookmarks/collections/{collectionId}") to
`@POST`("/api/v1/bookmarks/collections/{collectionId}")) so both endpoints
(getCollectionBookmarkUsers and toggleCollectionBookmark) use the same
absolute-path style.
In `@app/src/main/java/com/flint/data/dto/bookmark/CollectionBookmarkUsersDto.kt`:
- Around line 13-18: The User data class declares profileImageUrl as a
non-nullable String but other DTOs treat profile image URLs as nullable; update
the User data class (data class User) to make the profileImageUrl property of
type String? (nullable) so it matches RecommendCollectionResponseDto,
RecentCollectionListResponseDto, and CollectionDetailResponseDto and safely
handles API responses that may return null for profile images; ensure any usages
or mappings of User.profileImageUrl handle the nullable type accordingly.
In
`@app/src/main/java/com/flint/data/dto/collection/response/CollectionDetailResponseDto.kt`:
- Around line 6-37: Update the DTO to make fields that can be null according to
the API spec nullable: in CollectionDetailResponseDto change description: String
-> String? and thumbnailUrl: String -> String?; in nested Author keep
profileUrl: String? (already nullable); in nested Content change director:
String -> String?, reason: String -> String?, imageUrl: String -> String?, and
year: Int -> Int? (or keep Int if spec guarantees a value). Verify the API
contract and update the types in CollectionDetailResponseDto,
CollectionDetailResponseDto.Author.profileUrl, and
CollectionDetailResponseDto.Content (director, reason, imageUrl, year) to
String?/Int? as appropriate.
In
`@app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailViewModel.kt`:
- Around line 87-90: The onFailure block in CollectionDetailViewModel (inside
viewModelScope.launch) must not rethrow the exception because that will crash
the app; remove the throw it and instead set an error UiState or emit an error
event so the UI can show a dialog. Update the existing UiState to include an
Error case (or add a one-off event flow) and in the onFailure handler call the
appropriate state setter or emit function (e.g., update UiState to Error or send
via errorEventFlow) and log the exception for diagnostics; ensure the rest of
the coroutine continues to handle failure paths gracefully.
🧹 Nitpick comments (11)
app/src/main/java/com/flint/presentation/toast/ShowToast.kt (1)
27-32: 호출부 업데이트 여부 확인
paddingValues가 새 필수 파라미터라 기존 호출부가 모두 갱신되지 않으면 컴파일 오류가 납니다. 사용처가 전부 패딩 값을 전달하도록 확인해주세요. 필요하다면 기본값을 둬서 호환성을 유지하는 것도 고려해볼 수 있습니다.♻️ 선택적 개선: 기본값 제공
-fun ShowToast( - text: String, - imageVector: ImageVector?, - paddingValues: PaddingValues, - yOffset: Dp, - hide: () -> Unit, -) { +fun ShowToast( + text: String, + imageVector: ImageVector?, + paddingValues: PaddingValues = PaddingValues.Zero, + yOffset: Dp, + hide: () -> Unit, +) {Also applies to: 60-65, 78-83
app/src/main/java/com/flint/presentation/toast/ShowSaveToast.kt (1)
24-28: 호출부 업데이트 여부 확인
paddingValues가 새 필수 파라미터라 기존 호출부가 모두 갱신되지 않으면 컴파일 오류가 납니다. 사용처가 전부 패딩 값을 전달하도록 확인해주세요. 필요하다면 기본값을 둬서 호환성을 유지하는 것도 고려해볼 수 있습니다.♻️ 선택적 개선: 기본값 제공
-fun ShowSaveToast( - navigateToSavedCollection: () -> Unit, - paddingValues: PaddingValues, - yOffset: Dp, - hide: () -> Unit, -) { +fun ShowSaveToast( + navigateToSavedCollection: () -> Unit, + paddingValues: PaddingValues = PaddingValues.Zero, + yOffset: Dp, + hide: () -> Unit, +) {Also applies to: 55-59
app/src/main/java/com/flint/domain/model/AuthorModelNew.kt (1)
5-10:AuthorModelNew네이밍에 대한 제안클래스 이름에 "New" 접미사가 있는 것은 리팩토링 중임을 나타내지만, 장기적으로 코드 가독성을 저해할 수 있습니다. 기존
AuthorModel과의 통합이나 더 명확한 이름(예:CollectionAuthorModel)으로 변경을 고려해 주세요.app/src/main/java/com/flint/domain/model/content/ContentModel.kt (1)
6-16:ContentModelNew네이밍 일관성
AuthorModelNew와 동일하게 "New" 접미사가 사용되었습니다. 마이그레이션이 완료되면 기존ContentModel을 대체하거나 더 구체적인 이름(예:CollectionContentModel)으로 리팩토링을 계획해 주세요.구조와 필드 정의는 적절합니다.
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailEvent.kt (1)
3-7: LGTM! 이벤트 구조가 적절합니다.sealed interface를 사용한 이벤트 정의가 명확합니다. 향후
ToggleCollectionBookmarkSuccess를data class로 변경하면 디버깅 시toString()출력이 더 유용해질 수 있습니다.💡 선택적 개선안
sealed interface CollectionDetailEvent { - class ToggleCollectionBookmarkSuccess(val isBookmarked: Boolean) : CollectionDetailEvent + data class ToggleCollectionBookmarkSuccess(val isBookmarked: Boolean) : CollectionDetailEvent object ToggleCollectionBookmarkFailure : CollectionDetailEvent }app/src/main/java/com/flint/domain/repository/BookmarkRepository.kt (1)
21-22: 미구현 placeholder 코멘트가 있습니다.콘텐츠 북마크 토글 기능이 주석으로만 남아있습니다. 향후 구현 예정이라면 TODO 형식으로 변경하거나, 이번 PR 범위가 아니라면 제거를 고려해주세요.
app/src/main/java/com/flint/domain/model/collection/CollectionDetailModel.kt (3)
3-4: 도메인 모델에서 DTO를 직접 참조하고 있습니다.
CollectionDetailResponseDto를 도메인 모델 파일에서 직접 import하고 secondary constructor에서 사용하고 있습니다. 다른 매퍼 파일들(CollectionBookmarkUsersMapper.kt)처럼 별도의 mapper로 분리하면 계층 간 의존성이 명확해지고 일관성이 향상됩니다.
117-124:UserRoleType파싱 로직이 중복됩니다.
CollectionBookmarkUsersMapper.kt의 Line 20에 동일한runCatching { UserRoleType.valueOf(...) }.getOrDefault(UserRoleType.NONE)패턴이 있습니다. 공통 유틸리티 함수로 추출하면 유지보수성이 향상됩니다.♻️ 공통 유틸리티 예시
// UserRoleType.kt 또는 별도 유틸리티 파일에 추가 fun String.toUserRoleType(): UserRoleType = runCatching { UserRoleType.valueOf(this) }.getOrDefault(UserRoleType.NONE)
12-37:CollectionDetailModelNew네이밍을 확인해주세요.
CollectionDetailModel과CollectionDetailModelNew가 공존하는데, 마이그레이션 완료 후에는New접미사를 제거하고 기존 모델을 deprecated 처리하거나 정리하는 것이 좋습니다.app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailViewModel.kt (1)
71-84: API 호출 병렬화를 고려해 주세요.
collectionRepository.getCollectionDetail과bookmarkRepository.getCollectionBookmarkUsers가 순차적으로 호출되고 있습니다. 두 호출은 독립적이므로async를 사용하여 병렬로 실행하면 로딩 시간을 줄일 수 있습니다.♻️ 병렬 호출 예시
private fun getCollectionDetail(collectionId: String) { viewModelScope.launch { runCatching { coroutineScope { val collectionDetailDeferred = async { collectionRepository.getCollectionDetail(collectionId).getOrThrow() } val bookmarkUsersDeferred = async { bookmarkRepository.getCollectionBookmarkUsers(collectionId).getOrThrow() } UiState.Success( CollectionDetailUiState( collectionDetail = collectionDetailDeferred.await(), collectionBookmarkUsers = bookmarkUsersDeferred.await() ) ) } }.onSuccess { newUiState -> _uiState.update { newUiState } }.onFailure { // 에러 처리 } } }app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt (1)
69-72: 사용되지 않는 import 정리 필요
ContentModel과AuthorModelimport가 남아있습니다. Preview Provider를 수정한 후 이 import들이 여전히 필요한지 확인해 주세요.
- 북마크 상태 변경 시 `showSaveToast`와 `showCancelToast`가 동시에 활성화되지 않도록 명시적으로 수정 - `isProgressBarSticky` 변수에 타입 어노테이션 추가
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt (2)
365-466: Preview Provider 타입 불일치로 인한 컴파일 에러
PeoplePreviewProvider는ImmutableList<AuthorModel>을 반환하지만,PeopleWhoSavedThisCollectionPreview(Line 458)는ImmutableList<CollectionBookmarkUsersModel.User>를 기대합니다. 이로 인해 컴파일 에러가 발생합니다.Provider를
CollectionBookmarkUsersModel.User타입으로 업데이트해야 합니다.🐛 수정 제안
-private class PeoplePreviewProvider : PreviewParameterProvider<ImmutableList<AuthorModel>> { - override val values: Sequence<ImmutableList<AuthorModel>> = +private class PeoplePreviewProvider : PreviewParameterProvider<ImmutableList<CollectionBookmarkUsersModel.User>> { + override val values: Sequence<ImmutableList<CollectionBookmarkUsersModel.User>> = sequenceOf( persistentListOf( - AuthorModel( + CollectionBookmarkUsersModel.User( userId = "1", - nickname = "유저1", - profileUrl = "", + nickName = "유저1", + profileImageUrl = "", userRole = UserRoleType.FLING, ), ), // ... 나머지 항목들도 동일하게 수정 ) }
809-860: ContentPreviewProvider 타입 불일치로 인한 컴파일 에러
ContentPreviewProvider는ContentModel을 반환하지만,ContentPreview(Line 852)는ContentModelNew를 기대합니다. 필드명도 다릅니다 (contentId→id,posterImage→imageUrl,description→reason).🐛 수정 제안
-private class ContentPreviewProvider : PreviewParameterProvider<ContentModel> { - override val values: Sequence<ContentModel> = +private class ContentPreviewProvider : PreviewParameterProvider<ContentModelNew> { + override val values: Sequence<ContentModelNew> = sequenceOf( - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "드라마 제목", year = 2000, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix, OttType.Disney), + imageUrl = "", director = "가스 제닝스", - description = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", + reason = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", isSpoiler = false, isBookmarked = false, + bookmarkCount = 0, ), // ... 나머지 항목들도 동일하게 수정 ) }
🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt`:
- Around line 119-120: Replace the empty else branch with a specific
UiState.Failure case: handle UiState.Failure by rendering an error UI (e.g., a
Text showing failure.message or localized text and a Button labeled “Retry”),
and wire the Button to the retry action (call the existing retry function or
viewModel.fetchCollection()/retryFetch()/onRetry lambda used elsewhere). Remove
the else -> {} and ensure you reference UiState.Failure in the when expression
inside CollectionDetailScreen so API errors display a message and let the user
retry.
- Around line 104-106: In CollectionDetailScreen.kt the Thumbnail prop is
assigning userId = collectionDetail.id (collection ID) instead of the
collection's owner, breaking the authorId != userId check; change the prop to
userId = collectionDetail.userId (use collectionDetail.userId) when calling
Thumbnail (the lines setting authorId, userId, isBookmarked) so the component
receives the actual author/user ID for correct bookmark/author checks.
- GET 요청 경로의 leading slash(`/`) 제거
- CollectionBookmarkUsersDto.User의 profileImageUrl 타입을 String?로 변경 - CollectionBookmarkUsersModel.User의 profileImageUrl 타입을 String?로 변경
- CollectionDetailResponseDto의 profileUrl을 profileImageUrl로 수정 - AuthorModelNew의 profileUrl을 profileImageUrl로 수정 - 관련 매퍼 함수(toDomain) 수정
452c427 to
c454e9b
Compare
- onFailure 블록에서 throw it 구문을 제거하여 에러 발생 시 앱이 크래시되지 않도록 수정
- `userId`에 전달되는 값을 `collectionDetail.id`에서 `collectionDetail.userId`로 변경
# Conflicts: # app/src/main/java/com/flint/domain/repository/CollectionRepository.kt
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt (1)
809-852:ContentPreviewProvider와ContentPreview간 타입 불일치로 컴파일 에러 발생
ContentPreviewProvider는ContentModel을 반환하지만,ContentPreview함수는ContentModelNew를 기대합니다. 이로 인해 컴파일 에러가 발생합니다.🐛 제안하는 수정
-private class ContentPreviewProvider : PreviewParameterProvider<ContentModel> { - override val values: Sequence<ContentModel> = +private class ContentPreviewProvider : PreviewParameterProvider<ContentModelNew> { + override val values: Sequence<ContentModelNew> = sequenceOf( - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "드라마 제목", year = 2000, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix, OttType.Disney), + imageUrl = "", director = "가스 제닝스", - description = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", + reason = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", isSpoiler = false, isBookmarked = false, + bookmarkCount = 0, ), - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "스포일러 있는 영화", year = 2024, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix), + imageUrl = "", director = "감독 이름", - description = "이 내용은 스포일러가 포함되어 있습니다.", + reason = "이 내용은 스포일러가 포함되어 있습니다.", isSpoiler = true, isBookmarked = false, + bookmarkCount = 0, ), - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "저장된 영화", year = 2023, - posterImage = "", - ottSimpleList = listOf(OttType.Watcha, OttType.Wave), + imageUrl = "", director = "다른 감독", - description = "내가 저장한 영화입니다.", + reason = "내가 저장한 영화입니다.", isSpoiler = false, isBookmarked = true, bookmarkCount = 42, ), ) }또한 Line 69의
ContentModelimport는 더 이상 사용되지 않으므로 제거할 수 있습니다.
🧹 Nitpick comments (4)
app/src/main/java/com/flint/domain/model/collection/CollectionDetailModel.kt (2)
23-36: DTO에서 도메인 모델로의 매핑을 별도 mapper로 분리하는 것을 고려해주세요.현재 secondary constructor에서 DTO 매핑 로직을 처리하고 있습니다. 이 프로젝트의 다른 파일들(예:
CollectionBookmarkUsersMapper.kt)처럼 별도의 mapper 확장 함수로 분리하면 일관성과 테스트 용이성이 향상됩니다.♻️ 제안하는 리팩토링
별도 mapper 파일 생성:
// CollectionDetailMapper.kt fun CollectionDetailResponseDto.toModel(userId: String): CollectionDetailModelNew { return CollectionDetailModelNew( author = author.toModel(), contents = contents.map { it.toModel() }.toImmutableList(), createdAt = createdAt, description = description, id = id, thumbnailUrl = thumbnailUrl, isBookmarked = isBookmarked, title = title, userId = userId ) }
117-124:UserRoleType파싱 실패 시 로깅 추가를 권장합니다.
runCatching으로 예외를 조용히 처리하고 있어 디버깅 시 문제 원인 파악이 어려울 수 있습니다.♻️ 제안하는 개선
private fun CollectionDetailResponseDto.Author.toModel(): AuthorModelNew { return AuthorModelNew( id = id, nickname = nickname, profileImageUrl = profileImageUrl, - userRole = runCatching { UserRoleType.valueOf(userRole) }.getOrDefault(UserRoleType.NONE) + userRole = runCatching { UserRoleType.valueOf(userRole) } + .onFailure { /* Log.w("CollectionDetail", "Unknown userRole: $userRole") */ } + .getOrDefault(UserRoleType.NONE) ) }app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailViewModel.kt (2)
73-77: 두 API 호출을 병렬로 실행하면 성능이 향상됩니다.현재
getCollectionDetail과getCollectionBookmarkUsers가 순차적으로 실행되고 있습니다. 두 호출이 독립적이므로async를 사용하여 병렬로 실행할 수 있습니다.♻️ 제안하는 개선
private fun getCollectionDetail(collectionId: String) { viewModelScope.launch { runCatching { + val collectionDetailDeferred = async { + collectionRepository.getCollectionDetail(collectionId).getOrThrow() + } + val bookmarkUsersDeferred = async { + bookmarkRepository.getCollectionBookmarkUsers(collectionId).getOrThrow() + } + val collectionDetail: CollectionDetailModelNew = - collectionRepository.getCollectionDetail(collectionId).getOrThrow() + collectionDetailDeferred.await() val collectionBookmarkUsers: CollectionBookmarkUsersModel = - bookmarkRepository.getCollectionBookmarkUsers(collectionId).getOrThrow() + bookmarkUsersDeferred.await()
coroutineScopeimport 추가:import kotlinx.coroutines.async
87-89: 실패 시UiState가Loading상태로 남아있는 문제
onFailure블록이 비어있어 API 호출 실패 시 UI가 로딩 상태에서 벗어나지 못합니다. 이전 리뷰에서 언급된 대로 전체 화면 통합 에러 처리 예정이시라면, 최소한UiState.Failure로 상태를 업데이트하는 것이 좋습니다.♻️ 제안하는 최소한의 처리
}.onFailure { // TODO: 데이터 불러오지 못한 경우, 다이얼로그 띄우도록 구현 + _uiState.update { UiState.Failure(it) } }
…패키지 이동 - `CollectionDetailEvent` 클래스를 삭제하고 `sideeffect` 패키지에 `CollectionDetailSideEffect` 생성 - `CollectionDetailViewModel`에서 `event` 변수를 `sideEffect`로 변경 - `CollectionDetailScreen`에서 `viewModel.event` 대신 `viewModel.sideEffect`를 관찰하도록 수정
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt (1)
810-853:ContentPreviewProvider와ContentPreview간 타입 불일치
ContentPreviewProvider는PreviewParameterProvider<ContentModel>을 상속하지만,ContentPreview함수의 파라미터 타입은ContentModelNew입니다. 타입 불일치로 인해 컴파일 에러 또는 런타임 오류가 발생할 수 있습니다.🐛 수정 제안
-private class ContentPreviewProvider : PreviewParameterProvider<ContentModel> { - override val values: Sequence<ContentModel> = +private class ContentPreviewProvider : PreviewParameterProvider<ContentModelNew> { + override val values: Sequence<ContentModelNew> = sequenceOf( - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "드라마 제목", year = 2000, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix, OttType.Disney), + imageUrl = "", director = "가스 제닝스", - description = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", + reason = "달라진 온도\n-\n같은 구도에 채도를 달리해 변해버린 사랑을 시각적으로 담아낸 장면들", isSpoiler = false, isBookmarked = false, + bookmarkCount = 0, ), - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "스포일러 있는 영화", year = 2024, - posterImage = "", - ottSimpleList = listOf(OttType.Netflix), + imageUrl = "", director = "감독 이름", - description = "이 내용은 스포일러가 포함되어 있습니다.", + reason = "이 내용은 스포일러가 포함되어 있습니다.", isSpoiler = true, isBookmarked = false, + bookmarkCount = 0, ), - ContentModel( - contentId = "0", + ContentModelNew( + id = "0", title = "저장된 영화", year = 2023, - posterImage = "", - ottSimpleList = listOf(OttType.Watcha, OttType.Wave), + imageUrl = "", director = "다른 감독", - description = "내가 저장한 영화입니다.", + reason = "내가 저장한 영화입니다.", isSpoiler = false, isBookmarked = true, bookmarkCount = 42, ), ) }
🧹 Nitpick comments (1)
app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailViewModel.kt (1)
72-92: 독립적인 API 호출의 병렬 처리를 권장합니다.
getCollectionDetail과getCollectionBookmarkUsers는 서로 의존성이 없어 병렬로 실행할 수 있습니다. 순차 실행 시 불필요한 대기 시간이 발생합니다.♻️ async/await을 사용한 병렬 처리 제안
private fun getCollectionDetail(collectionId: String) { viewModelScope.launch { runCatching { - val collectionDetail: CollectionDetailModelNew = - collectionRepository.getCollectionDetail(collectionId).getOrThrow() - val collectionBookmarkUsers: CollectionBookmarkUsersModel = - bookmarkRepository.getCollectionBookmarkUsers(collectionId).getOrThrow() + val collectionDetailDeferred = async { + collectionRepository.getCollectionDetail(collectionId).getOrThrow() + } + val collectionBookmarkUsersDeferred = async { + bookmarkRepository.getCollectionBookmarkUsers(collectionId).getOrThrow() + } + + val collectionDetail: CollectionDetailModelNew = collectionDetailDeferred.await() + val collectionBookmarkUsers: CollectionBookmarkUsersModel = collectionBookmarkUsersDeferred.await() UiState.Success( CollectionDetailUiState( collectionDetail = collectionDetail, collectionBookmarkUsers = collectionBookmarkUsers ) ) }.onSuccess { newUiState: UiState.Success<CollectionDetailUiState> -> _uiState.update { newUiState } }.onFailure { // TODO: 데이터 불러오지 못한 경우, 다이얼로그 띄우도록 구현 } } }
async사용을 위해kotlinx.coroutines.asyncimport가 필요합니다.
- `PreferencesManager`의 패키지 위치를 `com.flint.core.common.datastore`에서 `com.flint.data.local`로 변경 - 사용하지 않는 import 제거 및 코드 포맷팅 수정
nahy-512
left a comment
There was a problem hiding this comment.
어푸푸🚀 저랑 스타일이 다른 부분이 많아서 이것저것 많이 여쭤봤네요ㅎㅎ 친절히 답변주셔서 너무 감사합니다! 작업 너무 고생하셨습니다
| @Composable | ||
| fun PeopleBottomSheet( | ||
| people: List<AuthorModel>, | ||
| people: List<CollectionBookmarkUsersModel.User>, |
There was a problem hiding this comment.
p2
ImmutableList로 받지 않고 있는 이유가 있나요?
📮 관련 이슈
📌 작업 내용
📸 스크린샷
view_collection.mp4
save_collection.mp4
back_click_collection.mp4
😅 미구현
🫛 To. 리뷰어
Summary by CodeRabbit
새로운 기능
개선사항
✏️ Tip: You can customize this high-level summary in your review settings.