[feat] #178 select-album 모듈 구현 및 upload-album 전환#185
[feat] #178 select-album 모듈 구현 및 upload-album 전환#185
Conversation
- feature:select-album (api, impl) 모듈 신규 생성 - app 모듈 및 settings.gradle.kts에 신규 모듈 의존성 추가
Walkthrough앱에서 UploadAlbum 기능(impl)을 제거하고 새 SelectAlbum 기능 모듈(api/impl)을 추가했습니다. Main 화면의 네비게이션·업로드 흐름과 ViewModel이 SelectAlbum 결과 기반으로 재연결되었고 관련 NavKey·EntryProvider·UI·ViewModel이 추가/삭제되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Main as Main Screen
participant MainVM as Main ViewModel
participant Navigator as MainNavigator
participant Select as SelectAlbum Screen
participant SelectVM as SelectAlbum ViewModel
participant Repo as Repository
participant Upload as Upload UseCase
participant Detail as AlbumDetail Screen
User->>Main: 앨범으로 업로드 클릭
Main->>MainVM: ClickUploadWithAlbum
MainVM->>Navigator: NavigateToSelectAlbum(photoCount)
Navigator->>Select: open SelectAlbum (with photoCount)
Select->>SelectVM: EnterSelectAlbumScreen
SelectVM->>Repo: load favorite + folders
Repo-->>SelectVM: album list
User->>Select: 선택 후 확인
Select->>SelectVM: ClickConfirmButton
SelectVM->>Navigator: SendResult(selectedAlbums) + goBack
Navigator->>Main: return SelectAlbumResult
Main->>MainVM: AlbumSelected(intent)
MainVM->>Upload: uploadSingleImage/uploadMultipleImages(..., album)
Upload->>Repo: upload (folderId = album?.id)
Repo-->>Upload: success
MainVM->>Navigator: NavigateToAlbumDetail(album.id, album.title)
Navigator->>Detail: navigateToAlbumDetail(id, title)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 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
🧹 Nitpick comments (1)
feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt (1)
125-148: 앨범 생성 중 로딩 표시 부재
handleAddAlbum에서 네트워크 요청 중 로딩 상태를 설정하지 않습니다. 사용자가 "추가하기" 버튼을 여러 번 클릭하면 중복 요청이 발생할 수 있습니다.🔧 로딩 상태 추가 제안
private fun handleAddAlbum( albumName: String, reduce: (SelectAlbumState.() -> SelectAlbumState) -> Unit, postSideEffect: (SelectAlbumSideEffect) -> Unit, ) { viewModelScope.launch { + reduce { copy(isLoading = true) } folderRepository.createFolder(name = albumName) .onSuccess { fetchFolders(reduce) reduce { copy( + isLoading = false, isShowAddAlbumBottomSheet = false, albumNameTextState = TextFieldState(), ) } postSideEffect(SelectAlbumSideEffect.ShowToastMessage("새로운 앨범을 추가했어요")) } .onFailure { e -> Timber.e(e) - reduce { copy(isShowAddAlbumBottomSheet = false, albumNameTextState = TextFieldState()) } + reduce { copy(isLoading = false, isShowAddAlbumBottomSheet = false, albumNameTextState = TextFieldState()) } postSideEffect(SelectAlbumSideEffect.ShowToastMessage("앨범 추가에 실패했어요")) } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt` around lines 125 - 148, The add-album flow in handleAddAlbum does not set a loading flag so duplicate taps can trigger multiple requests; before launching folderRepository.createFolder inside viewModelScope.launch, call reduce to set a new SelectAlbumState flag (e.g., isAddingAlbum or isLoadingAlbum = true) and disable the add button in the UI based on that flag, then after onSuccess and onFailure ensure you reset that flag to false (alongside the existing isShowAddAlbumBottomSheet and albumNameTextState updates); optionally, guard at the top of handleAddAlbum by checking the state flag and returning early if already loading to fully prevent concurrent requests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@feature/select-album/api/src/main/java/com/neki/android/feature/select_album/api/SelectAlbumNavKey.kt`:
- Line 7: Remove the unnecessary consecutive blank line in SelectAlbumNavKey.kt
that triggers Detekt's NoConsecutiveBlankLines rule (the extra empty line around
line 7); open the file containing the SelectAlbumNavKey declaration and delete
the extra blank line so there is only a single empty line between
sections/statements, then run Detekt/CI to confirm the warning is resolved.
In
`@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt`:
- Around line 69-73: SelectAlbumViewModel currently passes the raw album name
from the intent handler to handleAddAlbum without defensive
trimming/empty-checking; update the ClickAddAlbumConfirmButton handling in
SelectAlbumViewModel so that before calling handleAddAlbum you call .trim() on
state.albumNameTextState.text and skip/return early (or do not call
handleAddAlbum) if the trimmed string is empty, matching the pattern used in
ArchiveMainViewModel.handleAddAlbum; ensure reduce and postSideEffect are
preserved when calling handleAddAlbum.
---
Nitpick comments:
In
`@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt`:
- Around line 125-148: The add-album flow in handleAddAlbum does not set a
loading flag so duplicate taps can trigger multiple requests; before launching
folderRepository.createFolder inside viewModelScope.launch, call reduce to set a
new SelectAlbumState flag (e.g., isAddingAlbum or isLoadingAlbum = true) and
disable the add button in the UI based on that flag, then after onSuccess and
onFailure ensure you reset that flag to false (alongside the existing
isShowAddAlbumBottomSheet and albumNameTextState updates); optionally, guard at
the top of handleAddAlbum by checking the state flag and returning early if
already loading to fully prevent concurrent requests.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e6db1ab7-926d-427f-a80a-f2f6d956babe
📒 Files selected for processing (21)
app/build.gradle.ktsapp/src/main/java/com/neki/android/app/MainActivity.ktapp/src/main/java/com/neki/android/app/main/MainContract.ktapp/src/main/java/com/neki/android/app/main/MainScreen.ktapp/src/main/java/com/neki/android/app/main/MainViewModel.ktfeature/photo-upload/api/src/main/java/com/neki/android/feature/photo_upload/api/PhotoUploadNavKey.ktfeature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumContract.ktfeature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumScreen.ktfeature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumViewModel.ktfeature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/component/UploadAlbumTopBar.ktfeature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/di/PhotoUploadEntryProvider.ktfeature/select-album/api/build.gradle.ktsfeature/select-album/api/src/main/java/com/neki/android/feature/select_album/api/SelectAlbumNavKey.ktfeature/select-album/api/src/main/java/com/neki/android/feature/select_album/api/SelectAlbumResult.ktfeature/select-album/impl/build.gradle.ktsfeature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumContract.ktfeature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumScreen.ktfeature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumTopBar.ktfeature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.ktfeature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/navigation/SelectAlbumEntryProvider.ktsettings.gradle.kts
💤 Files with no reviewable changes (6)
- feature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/di/PhotoUploadEntryProvider.kt
- feature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/component/UploadAlbumTopBar.kt
- feature/photo-upload/api/src/main/java/com/neki/android/feature/photo_upload/api/PhotoUploadNavKey.kt
- feature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumContract.kt
- feature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumScreen.kt
- feature/photo-upload/impl/src/main/java/com/neki/android/feature/photo_upload/impl/album/UploadAlbumViewModel.kt
...elect-album/api/src/main/java/com/neki/android/feature/select_album/api/SelectAlbumNavKey.kt
Outdated
Show resolved
Hide resolved
...-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt
Show resolved
Hide resolved
...-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
♻️ Duplicate comments (1)
feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt (1)
65-69:⚠️ Potential issue | 🟡 Minor공백 앨범명이 생성 요청으로 전달될 수 있습니다.
Line 65-67에서 입력값을 그대로 넘겨
" "같은 값이 요청으로 전달될 수 있습니다. ViewModel에서trim()후 빈 값이면 조기 반환해 주세요. (이 이슈는 이전 리뷰에서도 이미 지적된 항목입니다.)제안 수정안
- SelectAlbumIntent.ClickAddAlbumConfirmButton -> handleAddAlbum( - albumName = state.albumNameTextState.text.toString(), - reduce = reduce, - postSideEffect = postSideEffect, - ) + SelectAlbumIntent.ClickAddAlbumConfirmButton -> { + val trimmedAlbumName = state.albumNameTextState.text.toString().trim() + if (trimmedAlbumName.isEmpty()) return + handleAddAlbum( + albumName = trimmedAlbumName, + reduce = reduce, + postSideEffect = postSideEffect, + ) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt` around lines 65 - 69, When handling SelectAlbumIntent.ClickAddAlbumConfirmButton, sanitize the input before calling handleAddAlbum: retrieve state.albumNameTextState.text, call trim() and if the resulting string is empty return early (do not call handleAddAlbum or post side effects); otherwise pass the trimmed string as albumName into handleAddAlbum so no whitespace-only names are sent to the request.
🧹 Nitpick comments (1)
feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt (1)
130-141: 성공/실패 분기의 바텀시트 초기화 로직이 중복됩니다.Line 130-135와 Line 140에서 동일 상태 초기화가 반복됩니다. 헬퍼로 추출하면 추후 상태 변경 시 누락 위험을 줄일 수 있습니다.
리팩터링 예시
+ private fun resetAddAlbumSheetState( + reduce: (SelectAlbumState.() -> SelectAlbumState) -> Unit, + ) { + reduce { + copy( + isShowAddAlbumBottomSheet = false, + albumNameTextState = TextFieldState(), + ) + } + } + private fun handleAddAlbum( albumName: String, reduce: (SelectAlbumState.() -> SelectAlbumState) -> Unit, postSideEffect: (SelectAlbumSideEffect) -> Unit, ) { viewModelScope.launch { folderRepository.createFolder(name = albumName) .onSuccess { fetchFolders(reduce) - reduce { - copy( - isShowAddAlbumBottomSheet = false, - albumNameTextState = TextFieldState(), - ) - } + resetAddAlbumSheetState(reduce) postSideEffect(SelectAlbumSideEffect.ShowToastMessage("새로운 앨범을 추가했어요")) } .onFailure { e -> Timber.e(e) - reduce { copy(isShowAddAlbumBottomSheet = false, albumNameTextState = TextFieldState()) } + resetAddAlbumSheetState(reduce) postSideEffect(SelectAlbumSideEffect.ShowToastMessage("앨범 추가에 실패했어요")) } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt` around lines 130 - 141, The reduce logic that resets isShowAddAlbumBottomSheet and albumNameTextState is duplicated in both the success and failure branches of the add-album flow; extract a single helper (e.g., a private method resetAddAlbumUiState or an inline function resetAddAlbumState) and call it from both the success path (after reduce { ... } currently) and the onFailure path before posting side effects, updating uses of reduce, SelectAlbumSideEffect, albumNameTextState, and isShowAddAlbumBottomSheet so the UI-reset behavior is centralized and only maintained in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In
`@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt`:
- Around line 65-69: When handling SelectAlbumIntent.ClickAddAlbumConfirmButton,
sanitize the input before calling handleAddAlbum: retrieve
state.albumNameTextState.text, call trim() and if the resulting string is empty
return early (do not call handleAddAlbum or post side effects); otherwise pass
the trimmed string as albumName into handleAddAlbum so no whitespace-only names
are sent to the request.
---
Nitpick comments:
In
`@feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt`:
- Around line 130-141: The reduce logic that resets isShowAddAlbumBottomSheet
and albumNameTextState is duplicated in both the success and failure branches of
the add-album flow; extract a single helper (e.g., a private method
resetAddAlbumUiState or an inline function resetAddAlbumState) and call it from
both the success path (after reduce { ... } currently) and the onFailure path
before posting side effects, updating uses of reduce, SelectAlbumSideEffect,
albumNameTextState, and isShowAddAlbumBottomSheet so the UI-reset behavior is
centralized and only maintained in one place.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 90a557b9-6173-48e5-8338-ed285d72aa0a
📒 Files selected for processing (1)
feature/select-album/impl/src/main/java/com/neki/android/feature/select_album/impl/SelectAlbumViewModel.kt
🔗 관련 이슈
📙 작업 설명
feature/select-album모듈(api/impl) 생성 및 의존성 설정upload-album제거 후select-album으로 전환🧪 테스트 내역 (선택)
📸 스크린샷 또는 시연 영상 (선택)
Screen_recording_20260410_015713.mp4
💬 추가 설명 or 리뷰 포인트 (선택)
photoCount: Int만 받아 상단 TopBar에 표시 (${photoCount}장 업로드)NavigateToAlbumDetail+RefreshArchive둘 다 post → AlbumDetail에서 뒤로가기 시 Archive 자동 갱신Summary by CodeRabbit
새로운 기능
개선사항