diff --git a/AuxioTODO b/AuxioTODO index 94d434c18..5e29058bb 100644 --- a/AuxioTODO +++ b/AuxioTODO @@ -24,19 +24,12 @@ TODO: /library/ -- Add genres - ? Move into ViewPager ? - Sorting - Search - ? Show Artists, Albums, and Songs in search ? - Exit functionality -/other/ - -- ? Condense detail fragments into a single fragment ? -- Condense artist/album recyclerview items into single item -- Remove binding adapters - To be added: /prefs/ /playback/ \ No newline at end of file diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 1884f7cc0..96072fec1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -33,12 +33,14 @@ class AlbumDetailFragment : Fragment() { // If DetailViewModel isn't already storing the album, get it from MusicViewModel // using the ID given by the navigation arguments. - if (detailModel.currentAlbum == null) { + if (detailModel.currentAlbum.value!!.id != args.albumId) { val musicModel: MusicViewModel by activityViewModels() - detailModel.currentAlbum = musicModel.albums.value!!.find { - it.id == args.albumId - }!! + detailModel.updateAlbum( + musicModel.albums.value!!.find { + it.id == args.albumId + }!! + ) } val songAdapter = DetailSongAdapter( @@ -49,7 +51,7 @@ class AlbumDetailFragment : Fragment() { binding.lifecycleOwner = this binding.detailModel = detailModel - binding.album = detailModel.currentAlbum + binding.album = detailModel.currentAlbum.value!! binding.albumSongRecycler.apply { adapter = songAdapter @@ -61,20 +63,16 @@ class AlbumDetailFragment : Fragment() { findNavController().navigateUp() } - // If the album was shown directly from LibraryFragment [No parent artist stored], - // then enable the ability to navigate upwards to the album's parent artist. - if (detailModel.currentArtist == null) { - detailModel.doneWithNavToParent() - - detailModel.navToParentArtist.observe(viewLifecycleOwner) { - if (it) { + // If the album was shown directly from LibraryFragment [No parent artist stored] + // Then enable the ability to navigate upwards to the parent artist + if (detailModel.currentArtist.value!!.id != detailModel.currentAlbum.value!!.artist.id) { + detailModel.currentArtist.observe(viewLifecycleOwner) { + if (it.id == detailModel.currentAlbum.value!!.artist.id) { findNavController().navigate( AlbumDetailFragmentDirections.actionShowParentArtist( - detailModel.currentAlbum!!.artist.id + detailModel.currentAlbum.value!!.artist.id ) ) - - detailModel.doneWithNavToParent() } } @@ -87,7 +85,7 @@ class AlbumDetailFragment : Fragment() { // Then update the sort mode of the album adapter. songAdapter.submitList( - detailModel.currentAlbum!!.songs.sortedWith( + detailModel.currentAlbum.value!!.songs.sortedWith( SortMode.songSortComparators.getOrDefault( mode, @@ -99,7 +97,7 @@ class AlbumDetailFragment : Fragment() { } // Don't enable the sort button if there's only one song [or less] - if (detailModel.currentAlbum!!.numSongs < 2) { + if (detailModel.currentAlbum.value!!.numSongs < 2) { binding.albumSortButton.imageTintList = ColorStateList.valueOf( R.color.inactive_color.toColor(requireContext()) ) @@ -111,10 +109,4 @@ class AlbumDetailFragment : Fragment() { return binding.root } - - override fun onDestroy() { - super.onDestroy() - - detailModel.currentAlbum = null - } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index 6ba6374fe..aae86b1f4 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -34,11 +34,14 @@ class ArtistDetailFragment : Fragment() { // If DetailViewModel isn't already storing the artist, get it from MusicViewModel // using the ID given by the navigation arguments - if (detailModel.currentArtist == null) { + if (detailModel.currentArtist.value!!.id != args.artistId) { val musicModel: MusicViewModel by activityViewModels() - detailModel.currentArtist = musicModel.artists.value!!.find { - it.id == args.artistId - }!! + + detailModel.updateArtist( + musicModel.artists.value!!.find { + it.id == args.artistId + }!! + ) } val albumAdapter = DetailAlbumAdapter( @@ -49,7 +52,7 @@ class ArtistDetailFragment : Fragment() { binding.lifecycleOwner = this binding.detailModel = detailModel - binding.artist = detailModel.currentArtist!! + binding.artist = detailModel.currentArtist.value!! binding.artistAlbumRecycler.apply { adapter = albumAdapter @@ -67,7 +70,7 @@ class ArtistDetailFragment : Fragment() { // Then update the sort mode of the album adapter. albumAdapter.submitList( - detailModel.currentArtist!!.albums.sortedWith( + detailModel.currentArtist.value!!.albums.sortedWith( SortMode.albumSortComparators.getOrDefault( mode, @@ -79,7 +82,7 @@ class ArtistDetailFragment : Fragment() { } // Don't enable the sort button if there is only one album [Or less] - if (detailModel.currentArtist!!.numAlbums < 2) { + if (detailModel.currentArtist.value!!.numAlbums < 2) { binding.artistSortButton.imageTintList = ColorStateList.valueOf( R.color.inactive_color.toColor(requireContext()) ) @@ -98,14 +101,6 @@ class ArtistDetailFragment : Fragment() { detailModel.isAlreadyNavigating = false } - override fun onDestroy() { - super.onDestroy() - - // Reset the stored artist so that the next instance of ArtistDetailFragment - // will not read it. - detailModel.currentArtist = null - } - private fun navToAlbum(album: Album) { // Don't navigate if an item already has been selected. if (!detailModel.isAlreadyNavigating) { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt index f5b81923f..ecf586320 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -11,9 +11,6 @@ import org.oxycblt.auxio.recycler.SortMode class DetailViewModel : ViewModel() { var isAlreadyNavigating = false - private val mNavToParentArtist = MutableLiveData() - val navToParentArtist: LiveData get() = mNavToParentArtist - private val mGenreSortMode = MutableLiveData(SortMode.ALPHA_DOWN) val genreSortMode: LiveData get() = mGenreSortMode @@ -23,16 +20,28 @@ class DetailViewModel : ViewModel() { private val mAlbumSortMode = MutableLiveData(SortMode.NUMERIC_DOWN) val albumSortMode: LiveData get() = mAlbumSortMode - var currentGenre: Genre? = null - var currentArtist: Artist? = null - var currentAlbum: Album? = null + // Current music models being shown + // These have placeholder values in them so that they don't + // have to be checked if they're null. + private val mCurrentGenre = MutableLiveData(Genre(name = "")) + val currentGenre: LiveData get() = mCurrentGenre - fun navToParent() { - mNavToParentArtist.value = true + private val mCurrentArtist = MutableLiveData(Artist(name = "")) + val currentArtist: LiveData get() = mCurrentArtist + + private val mCurrentAlbum = MutableLiveData(Album(name = "", artistName = "")) + val currentAlbum: LiveData get() = mCurrentAlbum + + fun updateGenre(genre: Genre) { + mCurrentGenre.value = genre } - fun doneWithNavToParent() { - mNavToParentArtist.value = false + fun updateArtist(artist: Artist) { + mCurrentArtist.value = artist + } + + fun updateAlbum(album: Album) { + mCurrentAlbum.value = album } fun incrementGenreSortMode() { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index ac03880d1..9b5017e1d 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -34,11 +34,14 @@ class GenreDetailFragment : Fragment() { // If DetailViewModel isn't already storing the genre, get it from MusicViewModel // using the ID given by the navigation arguments - if (detailModel.currentGenre == null) { + if (detailModel.currentGenre.value!!.id != args.genreId) { val musicModel: MusicViewModel by activityViewModels() - detailModel.currentGenre = musicModel.genres.value!!.find { - it.id == args.genreId - }!! + + detailModel.updateGenre( + musicModel.genres.value!!.find { + it.id == args.genreId + }!! + ) } val albumAdapter = DetailArtistAdapter( @@ -49,7 +52,7 @@ class GenreDetailFragment : Fragment() { binding.lifecycleOwner = this binding.detailModel = detailModel - binding.genre = detailModel.currentGenre!! + binding.genre = detailModel.currentGenre.value binding.genreArtistRecycler.adapter = albumAdapter binding.genreArtistRecycler.applyDivider() @@ -63,9 +66,9 @@ class GenreDetailFragment : Fragment() { // Update the current sort icon binding.genreSortButton.setImageResource(mode.iconRes) - // Then update the sort mode of the album adapter. + // Then update the sort mode of the artist adapter. albumAdapter.submitList( - detailModel.currentGenre!!.artists.sortedWith( + detailModel.currentGenre.value!!.artists.sortedWith( SortMode.artistSortComparators.getOrDefault( mode, @@ -77,7 +80,7 @@ class GenreDetailFragment : Fragment() { } // Don't enable the sort button if there is only one artist [Or less] - if (detailModel.currentGenre!!.numArtists < 2) { + if (detailModel.currentGenre.value!!.numArtists < 2) { binding.genreSortButton.imageTintList = ColorStateList.valueOf( R.color.inactive_color.toColor(requireContext()) ) @@ -96,14 +99,6 @@ class GenreDetailFragment : Fragment() { detailModel.isAlreadyNavigating = false } - override fun onDestroy() { - super.onDestroy() - - // Reset the stored artist so that the next instance of GenreDetailFragment - // will not read it. - detailModel.currentGenre = null - } - private fun navToArtist(artist: Artist) { // Don't navigate if an item already has been selected. if (!detailModel.isAlreadyNavigating) { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt index daec940e6..dd8a2b1b1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt @@ -3,9 +3,7 @@ package org.oxycblt.auxio.detail.adapters import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter -import org.oxycblt.auxio.databinding.ItemAlbumBinding import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding -import org.oxycblt.auxio.databinding.ItemArtistBinding import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.recycler.BaseViewHolder import org.oxycblt.auxio.recycler.ClickListener diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailArtistAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailArtistAdapter.kt index bda194b11..42cf088ba 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailArtistAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailArtistAdapter.kt @@ -3,10 +3,8 @@ package org.oxycblt.auxio.detail.adapters import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter -import org.oxycblt.auxio.databinding.ItemArtistBinding import org.oxycblt.auxio.databinding.ItemGenreArtistBinding import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.bindArtistCounts import org.oxycblt.auxio.recycler.BaseViewHolder import org.oxycblt.auxio.recycler.ClickListener import org.oxycblt.auxio.recycler.DiffCallback diff --git a/app/src/main/java/org/oxycblt/auxio/library/adapters/AlbumAdapter.kt b/app/src/main/java/org/oxycblt/auxio/library/adapters/AlbumAdapter.kt index a7114f4db..3d3fd3936 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/adapters/AlbumAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/adapters/AlbumAdapter.kt @@ -5,7 +5,6 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.ItemAlbumBinding import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.bindAlbumSongs import org.oxycblt.auxio.recycler.BaseViewHolder import org.oxycblt.auxio.recycler.ClickListener diff --git a/app/src/main/java/org/oxycblt/auxio/library/adapters/ArtistAdapter.kt b/app/src/main/java/org/oxycblt/auxio/library/adapters/ArtistAdapter.kt index 155dcc5fc..f54bafeba 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/adapters/ArtistAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/adapters/ArtistAdapter.kt @@ -5,7 +5,6 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.ItemArtistBinding import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.bindArtistCounts import org.oxycblt.auxio.recycler.BaseViewHolder import org.oxycblt.auxio.recycler.ClickListener diff --git a/app/src/main/java/org/oxycblt/auxio/music/Models.kt b/app/src/main/java/org/oxycblt/auxio/music/Models.kt index 9d60eafa9..8e1f32e31 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Models.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Models.kt @@ -25,7 +25,7 @@ data class Song( // Album data class Album( - override val id: Long = -1, + override val id: Long = Long.MIN_VALUE, override val name: String, val artistName: String, val coverUri: Uri = Uri.EMPTY, @@ -47,7 +47,7 @@ data class Album( // Artist data class Artist( - override val id: Long = -1, + override val id: Long = Long.MIN_VALUE, override var name: String, val givenGenres: MutableList = mutableListOf() ) : BaseModel() { @@ -67,7 +67,7 @@ data class Artist( // Genre data class Genre( - override val id: Long = -1, + override val id: Long = Long.MIN_VALUE, override var name: String, ) : BaseModel() { val artists = mutableListOf() diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt index 872826089..254e8a47b 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt @@ -1,7 +1,6 @@ package org.oxycblt.auxio.music import android.content.ContentUris -import android.content.Context import android.net.Uri import android.provider.MediaStore import android.text.format.DateUtils @@ -98,7 +97,11 @@ fun TextView.bindGenreCounts(genre: Genre) { // TODO: Add option to list all genres @BindingAdapter("artistGenre") fun TextView.bindArtistGenre(artist: Artist) { - text = artist.genres[0].name + text = if (artist.genres.isNotEmpty()) { + artist.genres[0].name + } else { + context.getString(R.string.placeholder_genre) + } } // Get the artist counts diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt index 425dfd3ff..89c92f3ad 100644 --- a/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt @@ -31,6 +31,7 @@ class SongAdapter( override fun onBind(model: Song) { binding.song = model + binding.songName.requestLayout() binding.songInfo.requestLayout() } diff --git a/app/src/main/res/layout/fragment_album_detail.xml b/app/src/main/res/layout/fragment_album_detail.xml index 0b8492858..ffd63e07e 100644 --- a/app/src/main/res/layout/fragment_album_detail.xml +++ b/app/src/main/res/layout/fragment_album_detail.xml @@ -77,7 +77,7 @@ android:layout_marginStart="@dimen/margin_medium" android:clickable="true" android:focusable="true" - android:onClick="@{() -> detailModel.navToParent()}" + android:onClick="@{() -> detailModel.updateArtist(album.artist)}" android:text="@{album.artist.name}" android:textAppearance="?android:attr/textAppearanceListItem" android:textColor="?android:attr/textColorSecondary"