Conversation
Database changes: - Add SongArtistCrossRef junction table for many-to-many relationships - Add SongWithArtists and ArtistWithSongs relation classes - Add albumArtist field to SongEntity - Add ArtistRef model and update Song model with artists list - Database migration 9→10 with junction table creation Preferences: - Add ARTIST_SEPARATION_ENABLED for toggling artist splitting - Add ARTIST_DELIMITERS for custom delimiter list (default: /, ;, ,, +, &) - Add GROUP_BY_ALBUM_ARTIST for album organization - Add ARTIST_SETTINGS_RESCAN_REQUIRED for pending library rescan Parsing logic: - Add splitArtistsByDelimiters() extension in Extensions.kt - Backslash escape support (\\) to preserve delimiters in names SyncWorker & DAO: - Query ALBUM_ARTIST from MediaStore - Split artists when enabled and create cross-references - Batch insert cross-refs in chunks of 500 - Efficient queries with JOINs for artist-song relationships UI Screens: - ArtistSettingsScreen: Toggles, delimiter config nav, info/examples cards - DelimiterConfigScreen: Add/remove delimiters with chips, reset option - Rescan warning banner when settings change - Navigation from Settings → Artists sub-screen
There was a problem hiding this comment.
Pull request overview
This pull request introduces comprehensive multi-artist support to the music player, allowing songs to have multiple associated artists through a many-to-many relationship. The implementation includes database schema updates with a junction table, intelligent artist parsing with configurable delimiters, and new UI screens for managing multi-artist settings.
Key changes:
- Database migration (v9→v10) with
SongArtistCrossRefjunction table for many-to-many artist-song relationships - Artist name parsing with configurable delimiters (/, ;, ,, +, &) and escape sequence support
- New settings screens for configuring multi-artist behavior and delimiter customization
- Updated data models to support multiple artists per song while maintaining backward compatibility
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
Extensions.kt |
Adds splitArtistsByDelimiters() function with escape sequence support and joinArtistsForDisplay() helper |
PlayerViewModel.kt |
Adds currentSongArtists StateFlow to expose all artists for the currently playing song |
ArtistSettingsViewModel.kt |
New ViewModel managing multi-artist configuration, delimiters, and rescan requirements |
SettingsScreen.kt |
Adds navigation entry to new Artist settings screen |
DelimiterConfigScreen.kt |
New screen for managing artist delimiter configuration with add/remove functionality |
ArtistSettingsScreen.kt |
New screen for multi-artist parsing settings, album artist grouping, and informational content |
Screen.kt |
Adds routes for ArtistSettings and DelimiterConfig screens |
AppNavigation.kt |
Registers navigation destinations for new artist configuration screens |
FullPlayerContent.kt |
Adds artist picker bottom sheet for multi-artist songs and updates artist navigation |
AppModule.kt |
Registers MIGRATION_9_10 in database builder |
SyncWorker.kt |
Implements multi-artist preprocessing logic with delimiter-based splitting and junction table population |
MusicRepositoryImpl.kt |
Adds getArtistsForSong() implementation and updates artist queries to use junction table |
MusicRepository.kt |
Adds getArtistsForSong() interface method |
UserPreferencesRepository.kt |
Adds preferences for artist separation, delimiters, album artist grouping, and rescan flags |
Song.kt |
Extends model with artists list, albumArtist field, and convenience properties |
LibraryModels.kt |
Adds ArtistRef data class for simplified artist references |
SongEntity.kt |
Adds albumArtist column and toSongWithArtists() conversion function |
SongArtistCrossRef.kt |
New junction table entity with supporting data classes for many-to-many queries |
PixelPlayDatabase.kt |
Increments version to 10 and adds MIGRATION_9_10 for junction table creation |
MusicDao.kt |
Adds extensive junction table query methods and transactional batch operations |
.idea/gradle.xml |
Updates Gradle JVM and home configuration |
Files not reviewed (1)
- .idea/gradle.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (current.size <= 1) return // Keep at least one delimiter | ||
|
|
||
| viewModelScope.launch { | ||
| userPreferencesRepository.setArtistDelimiters(current - delimiter) | ||
| } | ||
| } |
There was a problem hiding this comment.
The comment states 'Keep at least one delimiter', but the guard condition checks if size <= 1. This means if there's exactly 1 delimiter, the function returns early and doesn't remove it, which is correct. However, the logic in the UI (DelimiterConfigScreen lines 129-130) duplicates this check. If someone bypasses the ViewModel and calls setArtistDelimiters directly with an empty list, it would be allowed. Consider adding validation in setArtistDelimiters itself to ensure at least one delimiter is always maintained.
app/src/main/java/com/theveloper/pixelplay/data/database/SongEntity.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/theveloper/pixelplay/data/repository/MusicRepositoryImpl.kt
Outdated
Show resolved
Hide resolved
| songs.forEach { song -> | ||
| val artistsToProcess = if (artistSeparationEnabled) { | ||
| song.artistName.splitArtistsByDelimiters(artistDelimiters) | ||
| } else { | ||
| listOf(song.artistName) | ||
| } | ||
|
|
||
| artistsToProcess.forEach { artistName -> | ||
| val normalizedName = artistName.trim() | ||
| if (normalizedName.isNotEmpty() && !artistNameToId.containsKey(normalizedName)) { | ||
| // Check if this artist name matches the original artist in the song | ||
| // If so, use the original MediaStore ID | ||
| if (normalizedName == song.artistName) { | ||
| artistNameToId[normalizedName] = song.artistId | ||
| } else { | ||
| // Generate a new ID for split artists | ||
| artistNameToId[normalizedName] = nextArtistId.getAndIncrement() | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
In the first pass through songs, you're calling splitArtistsByDelimiters for each song, and then calling it again for the same songs in the second pass. This duplicates the splitting work. Consider caching the split results from the first pass in a map (songId -> List of artist names) to avoid redundant string processing, especially for large libraries.
There was a problem hiding this comment.
Can you fix that?
There was a problem hiding this comment.
Can you fix that?
app/src/main/java/com/theveloper/pixelplay/data/database/MusicDao.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/theveloper/pixelplay/presentation/components/player/FullPlayerContent.kt
Outdated
Show resolved
Hide resolved
| @Suppress("unused") | ||
| private fun preProcessAndDeduplicate(songs: List<SongEntity>): Triple<List<SongEntity>, List<AlbumEntity>, List<ArtistEntity>> { |
There was a problem hiding this comment.
The @Suppress("unused") annotation on the legacy preProcessAndDeduplicate function suggests it's kept for reference only. If this function is truly unused and only kept as reference, consider removing it entirely to reduce code maintenance burden, or move it to documentation/comments if the implementation logic needs to be preserved for reference.
app/src/main/java/com/theveloper/pixelplay/data/database/PixelPlayDatabase.kt
Outdated
Show resolved
Hide resolved
…ents/player/FullPlayerContent.kt Co-authored-by: Copilot <[email protected]>
…ntity.kt Co-authored-by: Copilot <[email protected]>
…icRepositoryImpl.kt Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
…ker.kt Co-authored-by: Copilot <[email protected]>
…ker.kt Co-authored-by: Copilot <[email protected]>
…Dao.kt Co-authored-by: Copilot <[email protected]>
…PlayDatabase.kt Co-authored-by: Copilot <[email protected]>
…ents/player/FullPlayerContent.kt Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
|
@copilot check again, i did the commits you requested. |
Co-authored-by: lostf1sh <[email protected]>
Co-authored-by: lostf1sh <[email protected]>
Co-authored-by: lostf1sh <[email protected]>
Co-authored-by: lostf1sh <[email protected]>
Co-authored-by: lostf1sh <[email protected]>
Optimize multi-artist processing: cache split results and remove redundant operations
|
Great job! Thank you for this! |
This pull request introduces comprehensive support for multi-artist relationships in the music database, enabling each song to have multiple associated artists and each artist to be linked with multiple songs. The migration is carefully handled to maintain backward compatibility and ensure efficient queries. The changes span database schema updates, model enhancements, and new DAO methods, as well as the addition of related user preferences.
Database schema and migration for multi-artist support:
SongArtistCrossRefjunction table to represent the many-to-many relationship between songs and artists, including a flag for the primary artist. The database version is incremented, and a migration is provided to populate this table from existing data. (app/src/main/java/com/theveloper/pixelplay/data/database/SongArtistCrossRef.kt,app/src/main/java/com/theveloper/pixelplay/data/database/PixelPlayDatabase.kt) [1] [2] [3]SongEntitymodel to add analbumArtistcolumn and adjusted conversion functions to handle the new structure. (app/src/main/java/com/theveloper/pixelplay/data/database/SongEntity.kt) [1] [2] [3] [4] [5]MusicDaointerface with new methods for managing and querying the song-artist cross-references, including batch inserts, deletions, and retrievals for both songs and artists. Transactional methods are provided for bulk operations. (app/src/main/java/com/theveloper/pixelplay/data/database/MusicDao.kt)Model and API enhancements:
ArtistRefdata class for simplified artist references and updated theSongmodel to include a list ofArtistRefobjects, analbumArtistfield, and helper properties for display and primary artist access. (app/src/main/java/com/theveloper/pixelplay/data/model/LibraryModels.kt,app/src/main/java/com/theveloper/pixelplay/data/model/Song.kt) [1] [2] [3]User preferences for multi-artist features:
app/src/main/java/com/theveloper/pixelplay/data/preferences/UserPreferencesRepository.kt)IDE and build configuration:
.idea/gradle.xml)