music: extend equality impls
Extend the music equals/hashCode implementations to take into account the raw music. This way, items that change in non-UID metadata are actually considered different at runtime while UIDs can still persist the data in a stable manner.
This commit is contained in:
parent
d0a68353a7
commit
06885ba264
6 changed files with 36 additions and 34 deletions
|
@ -127,7 +127,7 @@ class PlaylistDetailFragment :
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.action_delete -> {
|
R.id.action_delete -> {
|
||||||
musicModel.createPlaylist()
|
musicModel.deletePlaylist(currentPlaylist)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
|
|
|
@ -34,10 +34,6 @@ import org.oxycblt.auxio.util.toUuidOrNull
|
||||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||||
import org.oxycblt.auxio.util.update
|
import org.oxycblt.auxio.util.update
|
||||||
|
|
||||||
// TODO: Entirely rework music equality such that it's not completely UID-focused and actually
|
|
||||||
// takes metadata into account
|
|
||||||
// TODO: Reduce need for raw objects to save some memory
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library-backed implementation of [Song].
|
* Library-backed implementation of [Song].
|
||||||
*
|
*
|
||||||
|
@ -45,7 +41,7 @@ import org.oxycblt.auxio.util.update
|
||||||
* @param musicSettings [MusicSettings] to for user parsing configuration.
|
* @param musicSettings [MusicSettings] to for user parsing configuration.
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class SongImpl(rawSong: RawSong, musicSettings: MusicSettings) : Song {
|
class SongImpl(private val rawSong: RawSong, musicSettings: MusicSettings) : Song {
|
||||||
override val uid =
|
override val uid =
|
||||||
// Attempt to use a MusicBrainz ID first before falling back to a hashed UID.
|
// Attempt to use a MusicBrainz ID first before falling back to a hashed UID.
|
||||||
rawSong.musicBrainzId?.toUuidOrNull()?.let { Music.UID.musicBrainz(MusicMode.SONGS, it) }
|
rawSong.musicBrainzId?.toUuidOrNull()?.let { Music.UID.musicBrainz(MusicMode.SONGS, it) }
|
||||||
|
@ -89,9 +85,9 @@ class SongImpl(rawSong: RawSong, musicSettings: MusicSettings) : Song {
|
||||||
override val album: Album
|
override val album: Album
|
||||||
get() = unlikelyToBeNull(_album)
|
get() = unlikelyToBeNull(_album)
|
||||||
|
|
||||||
// Note: Only compare by UID so songs that differ only in MBID are treated differently.
|
override fun hashCode() = 31 * uid.hashCode() + rawSong.hashCode()
|
||||||
override fun hashCode() = uid.hashCode()
|
override fun equals(other: Any?) =
|
||||||
override fun equals(other: Any?) = other is Song && uid == other.uid
|
other is SongImpl && uid == other.uid && rawSong == other.rawSong
|
||||||
|
|
||||||
private val artistMusicBrainzIds = rawSong.artistMusicBrainzIds.parseMultiValue(musicSettings)
|
private val artistMusicBrainzIds = rawSong.artistMusicBrainzIds.parseMultiValue(musicSettings)
|
||||||
private val artistNames = rawSong.artistNames.parseMultiValue(musicSettings)
|
private val artistNames = rawSong.artistNames.parseMultiValue(musicSettings)
|
||||||
|
@ -248,11 +244,15 @@ class AlbumImpl(
|
||||||
override val durationMs: Long
|
override val durationMs: Long
|
||||||
override val dateAdded: Long
|
override val dateAdded: Long
|
||||||
|
|
||||||
// Note: Append song contents to MusicParent equality so that Groups with
|
override fun hashCode(): Int {
|
||||||
// the same UID but different contents are not equal.
|
var hashCode = uid.hashCode()
|
||||||
override fun hashCode() = 31 * uid.hashCode() + songs.hashCode()
|
hashCode = 31 * hashCode + rawAlbum.hashCode()
|
||||||
|
hashCode = 31 * hashCode + songs.hashCode()
|
||||||
|
return hashCode
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?) =
|
override fun equals(other: Any?) =
|
||||||
other is AlbumImpl && uid == other.uid && songs == other.songs
|
other is AlbumImpl && uid == other.uid && rawAlbum == other.rawAlbum && songs == other.songs
|
||||||
|
|
||||||
private val _artists = mutableListOf<ArtistImpl>()
|
private val _artists = mutableListOf<ArtistImpl>()
|
||||||
override val artists: List<Artist>
|
override val artists: List<Artist>
|
||||||
|
@ -341,9 +341,18 @@ class ArtistImpl(
|
||||||
|
|
||||||
// Note: Append song contents to MusicParent equality so that artists with
|
// Note: Append song contents to MusicParent equality so that artists with
|
||||||
// the same UID but different songs are not equal.
|
// the same UID but different songs are not equal.
|
||||||
override fun hashCode() = 31 * uid.hashCode() + songs.hashCode()
|
override fun hashCode(): Int {
|
||||||
|
var hashCode = uid.hashCode()
|
||||||
|
hashCode = 31 * hashCode + rawArtist.hashCode()
|
||||||
|
hashCode = 31 * hashCode + songs.hashCode()
|
||||||
|
return hashCode
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?) =
|
override fun equals(other: Any?) =
|
||||||
other is ArtistImpl && uid == other.uid && songs == other.songs
|
other is ArtistImpl &&
|
||||||
|
uid == other.uid &&
|
||||||
|
rawArtist == other.rawArtist &&
|
||||||
|
songs == other.songs
|
||||||
|
|
||||||
override lateinit var genres: List<Genre>
|
override lateinit var genres: List<Genre>
|
||||||
|
|
||||||
|
@ -422,11 +431,15 @@ class GenreImpl(
|
||||||
override val artists: List<Artist>
|
override val artists: List<Artist>
|
||||||
override val durationMs: Long
|
override val durationMs: Long
|
||||||
|
|
||||||
// Note: Append song contents to MusicParent equality so that Groups with
|
override fun hashCode(): Int {
|
||||||
// the same UID but different contents are not equal.
|
var hashCode = uid.hashCode()
|
||||||
override fun hashCode() = 31 * uid.hashCode() + songs.hashCode()
|
hashCode = 31 * hashCode + rawGenre.hashCode()
|
||||||
|
hashCode = 31 * hashCode + songs.hashCode()
|
||||||
|
return hashCode
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?) =
|
override fun equals(other: Any?) =
|
||||||
other is GenreImpl && uid == other.uid && songs == other.songs
|
other is GenreImpl && uid == other.uid && rawGenre == other.rawGenre && songs == other.songs
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val distinctAlbums = mutableSetOf<Album>()
|
val distinctAlbums = mutableSetOf<Album>()
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.oxycblt.auxio.music.metadata.*
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class RawSong(
|
data class RawSong(
|
||||||
/**
|
/**
|
||||||
* The ID of the [SongImpl]'s audio file, obtained from MediaStore. Note that this ID is highly
|
* The ID of the [SongImpl]'s audio file, obtained from MediaStore. Note that this ID is highly
|
||||||
* unstable and should only be used for accessing the audio file.
|
* unstable and should only be used for accessing the audio file.
|
||||||
|
@ -95,7 +95,7 @@ class RawSong(
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class RawAlbum(
|
data class RawAlbum(
|
||||||
/**
|
/**
|
||||||
* The ID of the [AlbumImpl]'s grouping, obtained from MediaStore. Note that this ID is highly
|
* The ID of the [AlbumImpl]'s grouping, obtained from MediaStore. Note that this ID is highly
|
||||||
* unstable and should only be used for accessing the system-provided cover art.
|
* unstable and should only be used for accessing the system-provided cover art.
|
||||||
|
@ -142,7 +142,7 @@ class RawAlbum(
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class RawArtist(
|
data class RawArtist(
|
||||||
/** @see Music.UID */
|
/** @see Music.UID */
|
||||||
val musicBrainzId: UUID? = null,
|
val musicBrainzId: UUID? = null,
|
||||||
/** @see Music.name */
|
/** @see Music.name */
|
||||||
|
@ -184,7 +184,7 @@ class RawArtist(
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class RawGenre(
|
data class RawGenre(
|
||||||
/** @see Music.name */
|
/** @see Music.name */
|
||||||
val name: String? = null
|
val name: String? = null
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -61,7 +61,6 @@ class NewPlaylistDialog : ViewBindingDialogFragment<DialogPlaylistNameBinding>()
|
||||||
}
|
}
|
||||||
// TODO: Navigate to playlist if there are songs in it
|
// TODO: Navigate to playlist if there are songs in it
|
||||||
musicModel.createPlaylist(name, pendingPlaylist.songs)
|
musicModel.createPlaylist(name, pendingPlaylist.songs)
|
||||||
pickerModel.dropPendingAddition()
|
|
||||||
requireContext().showToast(R.string.lng_playlist_created)
|
requireContext().showToast(R.string.lng_playlist_created)
|
||||||
findNavController().apply {
|
findNavController().apply {
|
||||||
navigateUp()
|
navigateUp()
|
||||||
|
|
|
@ -156,11 +156,6 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
|
||||||
refreshPlaylistChoices(songs)
|
refreshPlaylistChoices(songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Drop any pending songs to add since a playlist has already been found for them. */
|
|
||||||
fun dropPendingAddition() {
|
|
||||||
_currentPendingSongs.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshPlaylistChoices(songs: List<Song>) {
|
private fun refreshPlaylistChoices(songs: List<Song>) {
|
||||||
val userLibrary = musicRepository.userLibrary ?: return
|
val userLibrary = musicRepository.userLibrary ?: return
|
||||||
_playlistChoices.value =
|
_playlistChoices.value =
|
||||||
|
|
|
@ -112,11 +112,6 @@ private class UserLibraryImpl(
|
||||||
override val playlists: List<Playlist>
|
override val playlists: List<Playlist>
|
||||||
get() = playlistMap.values.toList()
|
get() = playlistMap.values.toList()
|
||||||
|
|
||||||
init {
|
|
||||||
// TODO: Actually read playlists
|
|
||||||
createPlaylist("Playlist 1", deviceLibrary.songs.slice(58..200))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findPlaylist(uid: Music.UID) = playlistMap[uid]
|
override fun findPlaylist(uid: Music.UID) = playlistMap[uid]
|
||||||
|
|
||||||
override fun findPlaylist(name: String) = playlistMap.values.find { it.name.raw == name }
|
override fun findPlaylist(name: String) = playlistMap.values.find { it.name.raw == name }
|
||||||
|
|
Loading…
Reference in a new issue