music: improve sorting

Update sorting usage in-app so that it's only done when absolutely
necessary.
This commit is contained in:
Alexander Capehart 2023-05-25 13:45:34 -06:00
parent c2def19aee
commit b037cfb166
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 35 additions and 39 deletions

View file

@ -11,8 +11,10 @@
"appears on" section in the artist view "appears on" section in the artist view
#### What's Fixed #### What's Fixed
- Prevented options such as "Add to queue" from being selected on empty - Prevented options such as "Add to queue" from being selected on empty artists and playlists
artists and playlists - Fixed issue where an item would be indicated as "playing" after playback ended
- Items should no longer be indicated as playing if the currently playing song is not contained
within it
## 3.1.0 ## 3.1.0

View file

@ -430,9 +430,7 @@ constructor(
val list = mutableListOf<Item>() val list = mutableListOf<Item>()
val grouping = val grouping =
Sort(Sort.Mode.ByDate, Sort.Direction.DESCENDING) artist.explicitAlbums.groupByTo(sortedMapOf()) {
.albums(artist.explicitAlbums)
.groupByTo(sortedMapOf()) {
// Remap the complicated ReleaseType data structure into an easier // Remap the complicated ReleaseType data structure into an easier
// "AlbumGrouping" enum that will automatically group and sort // "AlbumGrouping" enum that will automatically group and sort
// the artist's albums. // the artist's albums.
@ -458,7 +456,7 @@ constructor(
// implicit album list into the mapping. // implicit album list into the mapping.
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(grouping as MutableMap<AlbumGrouping, List<Album>>)[AlbumGrouping.APPEARANCES] = (grouping as MutableMap<AlbumGrouping, List<Album>>)[AlbumGrouping.APPEARANCES] =
Sort(Sort.Mode.ByDate, Sort.Direction.DESCENDING).albums(artist.implicitAlbums) artist.implicitAlbums
} }
logD("Release groups for this artist: ${grouping.keys}") logD("Release groups for this artist: ${grouping.keys}")

View file

@ -29,6 +29,7 @@ import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPlural import org.oxycblt.auxio.util.getPlural
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
/** /**
* A [DetailHeaderAdapter] that shows [Artist] information. * A [DetailHeaderAdapter] that shows [Artist] information.
@ -91,6 +92,7 @@ private constructor(private val binding: ItemDetailHeaderBinding) :
// The artist does not have any songs, so hide functionality that makes no sense. // The artist does not have any songs, so hide functionality that makes no sense.
// ex. Play and Shuffle, Song Counts, and Genre Information. // ex. Play and Shuffle, Song Counts, and Genre Information.
// Artists are always guaranteed to have albums however, so continue to show those. // Artists are always guaranteed to have albums however, so continue to show those.
logD("Artist is empty, disabling genres and playback")
binding.detailSubhead.isVisible = false binding.detailSubhead.isVisible = false
binding.detailPlayButton.isEnabled = false binding.detailPlayButton.isEnabled = false
binding.detailShuffleButton.isEnabled = false binding.detailShuffleButton.isEnabled = false

View file

@ -83,7 +83,6 @@ private constructor(private val binding: ItemDetailHeaderBinding) :
editedPlaylist: List<Song>?, editedPlaylist: List<Song>?,
listener: DetailHeaderAdapter.Listener listener: DetailHeaderAdapter.Listener
) { ) {
// TODO: Debug perpetually re-binding images
binding.detailCover.bind(playlist, editedPlaylist) binding.detailCover.bind(playlist, editedPlaylist)
binding.detailType.text = binding.context.getString(R.string.lbl_playlist) binding.detailType.text = binding.context.getString(R.string.lbl_playlist)
binding.detailName.text = playlist.name.resolve(binding.context) binding.detailName.text = playlist.name.resolve(binding.context)

View file

@ -50,6 +50,7 @@ import okio.buffer
import okio.source import okio.source
import org.oxycblt.auxio.image.CoverMode import org.oxycblt.auxio.image.CoverMode
import org.oxycblt.auxio.image.ImageSettings import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
@ -81,7 +82,12 @@ constructor(
} }
fun computeAlbumOrdering(songs: List<Song>) = fun computeAlbumOrdering(songs: List<Song>) =
songs.groupBy { it.album }.entries.sortedByDescending { it.value.size }.map { it.key } Sort(Sort.Mode.ByAlbum, Sort.Direction.ASCENDING)
.songs(songs)
.groupBy { it.album }
.entries
.sortedByDescending { it.value.size }
.map { it.key }
private suspend fun openInputStream(album: Album): InputStream? = private suspend fun openInputStream(album: Album): InputStream? =
try { try {

View file

@ -341,8 +341,6 @@ interface Artist : MusicParent {
* @author Alexander Capehart (OxygenCobalt) * @author Alexander Capehart (OxygenCobalt)
*/ */
interface Genre : MusicParent { interface Genre : MusicParent {
/** The albums indirectly linked to by the [Song]s of this [Genre]. */
val albums: List<Album>
/** The artists indirectly linked to by the [Artist]s of this [Genre]. */ /** The artists indirectly linked to by the [Artist]s of this [Genre]. */
val artists: List<Artist> val artists: List<Artist>
/** The total duration of the songs in this genre, in milliseconds. */ /** The total duration of the songs in this genre, in milliseconds. */
@ -355,8 +353,6 @@ interface Genre : MusicParent {
* @author Alexander Capehart (OxygenCobalt) * @author Alexander Capehart (OxygenCobalt)
*/ */
interface Playlist : MusicParent { interface Playlist : MusicParent {
/** The albums indirectly linked to by the [Song]s of this [Playlist]. */
val albums: List<Album>
/** The total duration of the songs in this genre, in milliseconds. */ /** The total duration of the songs in this genre, in milliseconds. */
val durationMs: Long val durationMs: Long
} }

View file

@ -387,9 +387,9 @@ class ArtistImpl(
} }
songs = distinctSongs.toList() songs = distinctSongs.toList()
albums = albumMap.keys.toList() albums = Sort(Sort.Mode.ByDate, Sort.Direction.DESCENDING).albums(albumMap.keys)
explicitAlbums = albumMap.entries.filter { it.value }.map { it.key } explicitAlbums = albums.filter { unlikelyToBeNull(albumMap[it]) }
implicitAlbums = albumMap.entries.filterNot { it.value }.map { it.key } implicitAlbums = albums.filterNot { unlikelyToBeNull(albumMap[it]) }
durationMs = songs.sumOf { it.durationMs }.nonZeroOrNull() durationMs = songs.sumOf { it.durationMs }.nonZeroOrNull()
} }
@ -436,7 +436,6 @@ class GenreImpl(
rawGenre.name?.let { Name.Known.from(it, rawGenre.name, musicSettings) } rawGenre.name?.let { Name.Known.from(it, rawGenre.name, musicSettings) }
?: Name.Unknown(R.string.def_genre) ?: Name.Unknown(R.string.def_genre)
override val albums: List<Album>
override val artists: List<Artist> override val artists: List<Artist>
override val durationMs: Long override val durationMs: Long
@ -462,10 +461,6 @@ class GenreImpl(
totalDuration += song.durationMs totalDuration += song.durationMs
} }
albums =
Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING)
.albums(distinctAlbums)
.sortedByDescending { album -> album.songs.count { it.genres.contains(this) } }
artists = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).artists(distinctArtists) artists = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).artists(distinctArtists)
durationMs = totalDuration durationMs = totalDuration
} }

View file

@ -33,8 +33,6 @@ private constructor(
override val songs: List<Song> override val songs: List<Song>
) : Playlist { ) : Playlist {
override val durationMs = songs.sumOf { it.durationMs } override val durationMs = songs.sumOf { it.durationMs }
override val albums =
songs.groupBy { it.album }.entries.sortedByDescending { it.value.size }.map { it.key }
/** /**
* Clone the data in this instance to a new [PlaylistImpl] with the given [name]. * Clone the data in this instance to a new [PlaylistImpl] with the given [name].