Optim/player view model migration phase 7#887
Merged
theovilardo merged 7 commits intomasterfrom Jan 22, 2026
Merged
Conversation
…tateHolders
Phase 1:
Extends the modularization of `PlayerViewModel` by extracting connectivity tracking and sleep timer management into standalone components. This reduces the boilerplate and responsibility surface of the main ViewModel.
- **ConnectivityStateHolder**:
- Centralizes WiFi and Bluetooth state tracking (enabled status, network/device names, connected audio devices).
- Manages system callbacks for `ConnectivityManager`, `WifiManager`, and `BluetoothManager`.
- Handles permission checks for Bluetooth and Location required for connectivity info.
- **SleepTimerStateHolder**:
- Manages duration-based sleep timers using `AlarmManager` for system-level reliability.
- Implements End-of-Track (EOT) monitoring to pause playback when a specific song finishes.
- Handles "Counted Play" logic to stop playback after a defined number of tracks.
- Maintains UI state for timer displays and countdowns.
- **PlayerViewModel**:
- Delegated all connectivity and sleep timer StateFlows and methods to the new holders.
- Reduced constructor complexity by replacing direct system service dependencies with the new StateHolders.
- Cleaned up manual `BroadcastReceiver` and callback registrations.
- **Documentation**: Added `PLAYER_VIEW_MODEL_ANALYSIS.md` providing a comprehensive architectural audit and migration plan for further decomposition.
- Decouples `PlayerViewModel` by delegating core responsibilities to specialized state holders: `LibraryStateHolder` for music data management, `MetadataEditStateHolder` for file modifications, and `ExternalMediaStateHolder` for URI-based playback. - Replaces paginated library song loading with a full-list approach in `LibrarySongsTab` and `LibraryScreen` to improve sorting consistency and UI responsiveness. - Implements `LibraryStateHolder` to centralize loading, sorting, and state management for songs, albums, artists, and folders. - Extends `UserPreferencesRepository` and `DailyMixStateHolder` to support persisting and loading "Your Mix" song IDs. - Enhances `AudioMetadataReader` to extract additional technical metadata including `albumArtist`, `bitrate`, and `sampleRate` using TagLib. - Adds `getAllSongsOnce()` to `MusicRepository` and `MusicDao` for efficient one-shot retrieval of the entire music library. - Optimizes `SortOption` by utilizing lazy initialization for static option lists. - Fixes a potential metadata loss issue in `MetadataEditStateHolder` by explicitly preserving existing embedded artwork during text-only edits.
… item building into specialized components. - Introduces `PlaybackStateHolder` to centralize playback controls (play/pause, seek, skip), shuffle/repeat logic, and progress tracking. - Implements `MediaItemBuilder` to unify the creation of `MediaItem` and `MediaMetadata` with consistent extra bundle keys for song metadata. - Migrates shuffle and queue manipulation logic to `QueueUtils`. - Refactors `PlayerViewModel` to delegate playback state and control responsibilities to `PlaybackStateHolder`. - Improves state synchronization between local playback and Cast sessions within the new state holder. - Cleans up `PlayerViewModel` by removing redundant constants and helper methods now managed by utility classes.
…e media server foreground management.
- **Refactor Cast Logic**:
- Extracts Cast session management and playback transfer logic from `PlayerViewModel` into a new `CastTransferStateHolder`.
- Centralizes remote status updates, queue synchronization, and the "transfer back" logic to local playback.
- Simplifies `PlayerViewModel` by delegating remote playback commands and state observation to the new holder.
- **Enhance Media Server**:
- Updates `MediaFileHttpServerService` to automatically start as a foreground service with a persistent notification.
- Adds `foregroundServiceType="mediaPlayback"` to the manifest for the HTTP server to comply with Android's foreground service requirements.
- **Player Engine Robustness**:
- Introduces an `initialize()` method in `DualPlayerEngine` to safely handle player recreation if the service is restarted.
- Ensures `MusicService` calls `engine.initialize()` during `onCreate` to guarantee the underlying `ExoPlayer` instances are ready.
- Adds safety checks in `DualPlayerEngine.release()` to prevent null pointer exceptions on uninitialized players.
…izing logic into dedicated state holders and externalizing data models.
- **Modularize ViewModels**:
- Moves `PlayerUiState`, `StablePlayerState`, `PlayerSheetState`, `ColorSchemePair`, and `LyricsSearchUiState` into separate files for better maintainability and code organization.
- Introduces `ThemeStateHolder` to manage album art color extraction, dynamic palette generation, and the "lava lamp" background colors.
- Relocates genre generation logic and state into `LibraryStateHolder`.
- Moves repeat mode management and shuffle preparation logic into `PlaybackStateHolder` and `QueueStateHolder` respectively.
- **Enhance Theme Processing**:
- Implements an asynchronous color scheme extraction flow in `ThemeStateHolder` using a centralized `ColorSchemeProcessor`.
- Adds `getAlbumColorSchemeFlow()` with LRU caching to efficiently handle per-album color palettes in list views (e.g., `LibraryScreen`).
- **Improve Playback Logic**:
- Refactors `playSongsShuffled` to use `QueueStateHolder` for Atomic queue preparation, preventing race conditions during shuffle transitions.
- Centralizes repeat mode updates (Off/One) into `PlaybackStateHolder.setRepeatMode()`, ensuring consistency across local and Cast playback.
- Automates lyrics sync offset updates in `LyricsStateHolder` by observing song changes within its initialization.
- **UI Refinement**:
- Updates `LibraryScreen` to utilize the new `ThemeStateHolder` for fetching album-specific color schemes.
- Cleans up `PlayerViewModel` by removing redundant state variables and delegating implementation details to injected helper classes.
…e holders and helper classes - Introduces `ImageCacheManager` to centralize Coil image cache invalidation for cover art. - Introduces `MediaMapper` to handle the conversion of `MediaItem` objects to `Song` models. - Refactors `PlayerViewModel` by delegating Google Cast discovery and management logic to `CastStateHolder`. - Enhances `LyricsStateHolder` to manage remote lyrics fetching, manual searching, and file importing, reducing the ViewModel's responsibility. - Replaces inline MediaRouter callback logic in `PlayerViewModel` with a more robust implementation within `CastStateHolder`. - Updates `PlayerViewModel` to observe song and message events from `LyricsStateHolder` for UI synchronization. - Simplifies `resolveSongFromMediaItem` and `invalidateCoverArtCaches` by utilizing the new helper classes.
- Updates `MainActivity` to use real library data instead of dummy data when benchmarking. - Significantly reduces `PlayerViewModel` complexity by removing unused imports, constants, and private helper functions. - Streamlines `PlayerViewModel` initialization and data loading by delegating more responsibilities to specialized state holders (e.g., `LibraryStateHolder`, `ThemeStateHolder`). - Removes redundant or unused state flows like `paginatedSongs`, `isSheetVisible`, and `playerThemePreference`. - Cleans up playback logic, removing unused methods for repeat modes and redundant queue matching helpers. - Simplifies theme preloading and library data fetching, utilizing parallel execution via delegated holders. - Removes manual artwork loading logic in favor of existing infrastructure. - Deletes dead code related to folder filtering and old benchmark data generation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PlayerViewModel refactored and optimized using StateHolders