Skip to content

refactor: ViewModel 일관성 개선 및 MiniPlayer 상태 생성 로직 중복 제거#80

Merged
gagip merged 5 commits intomainfrom
refactor/viewmodel-consistency
Mar 26, 2026
Merged

refactor: ViewModel 일관성 개선 및 MiniPlayer 상태 생성 로직 중복 제거#80
gagip merged 5 commits intomainfrom
refactor/viewmodel-consistency

Conversation

@gagip
Copy link
Copy Markdown
Owner

@gagip gagip commented Mar 26, 2026

Summary

  • ViewModel의 퍼블릭 API를 onAction() 단일 진입점 패턴으로 통일하고, 여러 ViewModel에 중복된 MiniPlayer 상태 생성 로직을 공통 확장 함수로 추출함

Key Changes

  • PlaylistDetailViewModel: 퍼블릭 메서드(selectPlaylist, playPlaylist, removeTrackFromPlaylist)를 private으로 전환하고 onAction(PlaylistDetailAction) 단일 진입점 추가
  • PlaylistDetailAction: MiniPlayer 래퍼 액션 제거, SelectPlaylist 액션 추가
  • ZenPlayerServiceBinderExtensions.kt 신규 추가: miniPlayerUiState(), miniPlayerProgress() 공통 확장 함수
  • MiniPlayerViewModel, ZenMusicSelectViewModel: 중복된 MiniPlayer/progress Flow 생성 코드를 공통 확장 함수로 대체
  • PlaylistDetailScreen: onMiniPlayerAction 콜백을 별도 파라미터로 분리 (onAction 내부 래핑 제거)
  • 의도 설명 주석 추가: WhileSubscribed5s 미사용 이유, 상수 분리 의도

Technical Details

  • ZenPlayerServiceBinderminiPlayerUiState(scope), miniPlayerProgress(scope) 확장 함수를 정의하여 binderFlow.whenNonNull + combine + stateIn 패턴을 단일 구현으로 집약
  • NavGraph에서 PlaylistDetailAction.MiniPlayer 래핑 대신 miniPlayerViewModel.onAction() 직접 호출로 변경
  • 테스트 코드도 공개 API 변경에 맞춰 onAction() 호출 방식으로 업데이트

Rationale

  • ViewModel 퍼블릭 API를 onAction() 단일 진입점으로 통일하면 호출부의 ViewModel 내부 구조 의존도가 낮아짐
  • MiniPlayer 상태 생성 로직이 2개 이상의 ViewModel에 동일하게 복사되어 있어, 변경 시 모두 수정해야 하는 유지보수 비용을 확장 함수 추출로 해소
  • PlaylistDetailAction.MiniPlayer 래퍼는 관심사가 다른 액션을 억지로 묶은 형태로, 분리가 더 명확한 구조

gagip added 5 commits March 26, 2026 12:56
selectPlaylist/removeTrackFromPlaylist/playPlaylist를 private으로 변경하고
onAction()을 통해서만 접근하도록 통일. PlaylistDetailAction에 SelectPlaylist
액션 추가, NavGraph와 테스트 코드도 onAction() 방식으로 업데이트.
PlaylistDetailViewModel과 AudioPermissionHandler는 외부 Flow 구독 없이
직접 값을 push하거나 ViewModel 생명주기 내내 상태를 유지해야 하므로
MutableStateFlow.asStateFlow()가 적합함을 주석으로 명시.
ZenPlayerServiceBinder 확장 함수(miniPlayerUiState, miniPlayerProgress)로
공통 로직을 core/service에 추출. MiniPlayerViewModel과
ZenMusicSelectViewModel의 중복 구현을 제거하고 공통 함수를 재사용.
TimerEngine.UPDATE_INTERVAL_MS와 ZenAudioController.POSITION_UPDATE_INTERVAL_MS는
값(100L)이 같지만 각각 타이머 UI 갱신, 재생 위치 추적이라는 독립적인 용도를 가지므로
공통 상수로 통합하지 않고 의도를 주석으로 명시.
- PlaylistDetailAction에서 MiniPlayer 케이스 제거 → Screen에 onMiniPlayerAction
  파라미터 분리, NavGraph에서 exhaustive when으로 컴파일러 안전망 복원
- MiniPlayerViewModel, ZenMusicSelectViewModel의 _binder 필드 제거 →
  serviceBinder.binderFlow에 직접 접근하여 불필요한 중간 필드 삭제
@github-actions
Copy link
Copy Markdown

Coverage Report

Module Coverage Covered Total
Total 19.31% 906 4692
Player 35.94% 101 281
Playlist 19.59% 77 393
Timer 48.15% 365 758
Music 21.08% 39 185

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

ViewModel 퍼블릭 API를 onAction() 단일 진입점 패턴으로 통일하고, 여러 ViewModel에 중복되어 있던 MiniPlayer UI/progress Flow 생성 로직을 ZenPlayerServiceBinder 확장 함수로 공통화하는 리팩터링입니다.

Changes:

  • PlaylistDetailViewModel의 공개 메서드를 onAction(PlaylistDetailAction)로 통합하고 액션 모델을 정리 (SelectPlaylist 추가, MiniPlayer 래퍼 제거)
  • MiniPlayer 상태/진행률 Flow 생성 로직을 ZenPlayerServiceBinderExtensions.kt로 추출하여 MiniPlayerViewModel, ZenMusicSelectViewModel에서 재사용
  • PlaylistDetailScreen의 MiniPlayer 액션 전달 경로를 별도 콜백(onMiniPlayerAction)으로 분리하고, 호출부/테스트를 새 API에 맞게 수정

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
app/src/test/java/com/happyseal/zenplayer/features/playlist/ui/PlaylistDetailViewModelTest.kt selectPlaylist/playPlaylist/removeTrackFromPlaylist 직접 호출 대신 onAction() 기반으로 테스트 갱신
app/src/main/java/com/happyseal/zenplayer/zen/musicselect/ZenMusicSelectViewModel.kt MiniPlayer/progress Flow 생성 중복 제거, binder 접근을 serviceBinder로 일원화
app/src/main/java/com/happyseal/zenplayer/zen/miniplayer/MiniPlayerViewModel.kt MiniPlayer/progress Flow 생성 로직을 공통 확장 함수로 치환
app/src/main/java/com/happyseal/zenplayer/features/timer/domain/TimerEngine.kt 타이머 UI 갱신 주기 상수의 “의도”를 설명하는 주석 추가
app/src/main/java/com/happyseal/zenplayer/features/playlist/ui/PlaylistDetailViewModel.kt onAction() 단일 진입점 도입 및 기존 공개 메서드 private 전환
app/src/main/java/com/happyseal/zenplayer/features/playlist/ui/PlaylistDetailScreen.kt MiniPlayer 액션 콜백을 onAction에서 분리해 onMiniPlayerAction으로 전달
app/src/main/java/com/happyseal/zenplayer/features/playlist/ui/PlaylistDetailAction.kt MiniPlayer 래퍼 제거, SelectPlaylist 액션 추가
app/src/main/java/com/happyseal/zenplayer/features/player/data/ZenAudioController.kt 재생 위치 갱신 주기 상수의 “의도”를 설명하는 주석 추가
app/src/main/java/com/happyseal/zenplayer/features/music/ui/AudioPermissionHandler.kt 권한 상태 Flow 유지 전략(항상 활성) 의도 주석 추가
app/src/main/java/com/happyseal/zenplayer/core/service/ZenPlayerServiceBinderExtensions.kt binderFlow 기반 MiniPlayer UI/progress StateFlow 생성 확장 함수 신규 추가
app/src/main/java/com/happyseal/zenplayer/core/navigation/NavGraph.kt PlaylistDetailViewModel 초기화/액션 전달을 onAction() 기반으로 변경, MiniPlayer 액션은 별도 콜백으로 위임

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gagip gagip marked this pull request as ready for review March 26, 2026 06:40
@gagip gagip merged commit 88ba8c7 into main Mar 26, 2026
5 checks passed
@gagip gagip deleted the refactor/viewmodel-consistency branch March 26, 2026 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants