diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 837d82e4e..3c128e671 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -175,6 +175,7 @@ class HomeFragment : // --- VIEWMODEL SETUP --- collect(homeModel.recreateTabs.flow, ::handleRecreate) + collect(homeModel.chooseMusicLocations.flow, ::handleChooseFolders) collectImmediately(homeModel.currentTabType, ::updateCurrentTab) collect(detailModel.toShow.flow, ::handleShow) collect(listModel.menu.flow, ::handleMenu) @@ -301,6 +302,16 @@ class HomeFragment : homeModel.recreateTabs.consume() } + private fun handleChooseFolders(unit: Unit?) { + if (unit == null) { + return + } + findNavController().navigateSafe( + HomeFragmentDirections.chooseLocations() + ) + homeModel.chooseMusicLocations.consume() + } + private fun updateIndexerState(state: IndexingState?) { // TODO: Make music loading experience a bit more pleasant // 1. Loading placeholder for item lists diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt index 4ebc98baf..63558b839 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -159,6 +159,10 @@ constructor( val showOuter: Event get() = _showOuter + private val _chooseMusicLocations = MutableEvent() + val chooseMusicLocations: Event + get() = _chooseMusicLocations + init { homeGenerator.attach() } @@ -263,6 +267,10 @@ constructor( _isFastScrolling.value = isFastScrolling } + fun startChooseMusicLocations() { + _chooseMusicLocations.put(Unit) + } + fun showSettings() { _showOuter.put(Outer.Settings) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt index 4d241eaf7..ca9b5cd9e 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt @@ -22,6 +22,7 @@ import android.os.Bundle import android.text.format.DateUtils import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isInvisible import androidx.fragment.app.activityViewModels import dagger.hilt.android.AndroidEntryPoint import java.util.Formatter @@ -37,6 +38,7 @@ import org.oxycblt.auxio.list.recycler.AlbumViewHolder import org.oxycblt.auxio.list.recycler.FastScrollRecyclerView import org.oxycblt.auxio.list.sort.Sort import org.oxycblt.auxio.music.Album +import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -79,7 +81,13 @@ class AlbumListFragment : listener = this@AlbumListFragment } - collectImmediately(homeModel.albumList, ::updateAlbums) + binding.homeNoMusicMsg.text = getString(R.string.lng_no_albums) + + binding.homeChooseMusicSources.setOnClickListener { + homeModel.startChooseMusicLocations() + } + + collectImmediately(homeModel.albumList, musicModel.indexingState, ::updateAlbums) collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -143,7 +151,11 @@ class AlbumListFragment : listModel.openMenu(R.menu.album, item) } - private fun updateAlbums(albums: List) { + private fun updateAlbums(albums: List, indexingState: IndexingState?) { + requireBinding().apply { + homeRecycler.isInvisible = indexingState is IndexingState.Indexing || albums.isEmpty() + homeNoMusic.isInvisible = albums.isEmpty() + } albumAdapter.update(albums, homeModel.albumInstructions.consume()) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt index b2e805a75..5e0290428 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt @@ -21,6 +21,7 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isInvisible import androidx.fragment.app.activityViewModels import dagger.hilt.android.AndroidEntryPoint import org.oxycblt.auxio.R @@ -35,6 +36,7 @@ import org.oxycblt.auxio.list.recycler.ArtistViewHolder import org.oxycblt.auxio.list.recycler.FastScrollRecyclerView import org.oxycblt.auxio.list.sort.Sort import org.oxycblt.auxio.music.Artist +import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -74,7 +76,13 @@ class ArtistListFragment : listener = this@ArtistListFragment } - collectImmediately(homeModel.artistList, ::updateArtists) + binding.homeNoMusicMsg.text = getString(R.string.lng_no_artists) + + binding.homeChooseMusicSources.setOnClickListener { + homeModel.startChooseMusicLocations() + } + + collectImmediately(homeModel.artistList, musicModel.indexingState, ::updateArtists) collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -119,7 +127,11 @@ class ArtistListFragment : listModel.openMenu(R.menu.parent, item) } - private fun updateArtists(artists: List) { + private fun updateArtists(artists: List, indexingState: IndexingState?) { + requireBinding().apply { + homeRecycler.isInvisible = indexingState is IndexingState.Indexing || artists.isEmpty() + homeNoMusic.isInvisible = artists.isEmpty() + } artistAdapter.update(artists, homeModel.artistInstructions.consume()) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt index 4ea68bb5c..86a8bc795 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt @@ -21,6 +21,7 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isInvisible import androidx.fragment.app.activityViewModels import dagger.hilt.android.AndroidEntryPoint import org.oxycblt.auxio.R @@ -35,6 +36,7 @@ import org.oxycblt.auxio.list.recycler.FastScrollRecyclerView import org.oxycblt.auxio.list.recycler.GenreViewHolder import org.oxycblt.auxio.list.sort.Sort import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -73,7 +75,13 @@ class GenreListFragment : listener = this@GenreListFragment } - collectImmediately(homeModel.genreList, ::updateGenres) + binding.homeNoMusicMsg.text = getString(R.string.lng_no_genres) + + binding.homeChooseMusicSources.setOnClickListener { + homeModel.startChooseMusicLocations() + } + + collectImmediately(homeModel.genreList, musicModel.indexingState, ::updateGenres) collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -118,7 +126,11 @@ class GenreListFragment : listModel.openMenu(R.menu.parent, item) } - private fun updateGenres(genres: List) { + private fun updateGenres(genres: List, indexingState: IndexingState?) { + requireBinding().apply { + homeRecycler.isInvisible = indexingState is IndexingState.Indexing || genres.isEmpty() + homeNoMusic.isInvisible = genres.isEmpty() + } genreAdapter.update(genres, homeModel.genreInstructions.consume()) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt index 901693eb9..ecfd99065 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt @@ -21,6 +21,7 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isInvisible import androidx.fragment.app.activityViewModels import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding @@ -33,6 +34,7 @@ import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.FastScrollRecyclerView import org.oxycblt.auxio.list.recycler.PlaylistViewHolder import org.oxycblt.auxio.list.sort.Sort +import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -71,7 +73,13 @@ class PlaylistListFragment : listener = this@PlaylistListFragment } - collectImmediately(homeModel.playlistList, ::updatePlaylists) + binding.homeNoMusicMsg.text = getString(R.string.lng_no_playlists) + + binding.homeChooseMusicSources.setOnClickListener { + homeModel.startChooseMusicLocations() + } + + collectImmediately(homeModel.playlistList, musicModel.indexingState, ::updatePlaylists) collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -116,7 +124,11 @@ class PlaylistListFragment : listModel.openMenu(R.menu.playlist, item) } - private fun updatePlaylists(playlists: List) { + private fun updatePlaylists(playlists: List, indexingState: IndexingState?) { + requireBinding().apply { + homeRecycler.isInvisible = indexingState is IndexingState.Indexing || playlists.isEmpty() + homeNoMusic.isInvisible = playlists.isEmpty() + } playlistAdapter.update(playlists, homeModel.playlistInstructions.consume()) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt index 1d455b58c..a48e18218 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt @@ -15,13 +15,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package org.oxycblt.auxio.home.list import android.os.Bundle import android.text.format.DateUtils import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isInvisible import androidx.fragment.app.activityViewModels import dagger.hilt.android.AndroidEntryPoint import java.util.Formatter @@ -35,6 +36,7 @@ import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.FastScrollRecyclerView import org.oxycblt.auxio.list.recycler.SongViewHolder import org.oxycblt.auxio.list.sort.Sort +import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -59,6 +61,7 @@ class SongListFragment : override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val songAdapter = SongAdapter(this) + // Save memory by re-using the same formatter and string builder when creating popup text private val formatterSb = StringBuilder(64) private val formatter = Formatter(formatterSb) @@ -76,10 +79,17 @@ class SongListFragment : listener = this@SongListFragment } - collectImmediately(homeModel.songList, ::updateSongs) + binding.homeNoMusicMsg.text = getString(R.string.lng_no_songs) + + binding.homeChooseMusicSources.setOnClickListener { + homeModel.startChooseMusicLocations() + } + + collectImmediately(homeModel.songList, musicModel.indexingState, ::updateSongs) collectImmediately(listModel.selected, ::updateSelection) collectImmediately( - playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) + playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback + ) } override fun onDestroyBinding(binding: FragmentHomeListBinding) { @@ -117,11 +127,12 @@ class SongListFragment : val dateAddedMillis = song.dateAdded.secsToMs() formatterSb.setLength(0) DateUtils.formatDateRange( - context, - formatter, - dateAddedMillis, - dateAddedMillis, - DateUtils.FORMAT_ABBREV_ALL) + context, + formatter, + dateAddedMillis, + dateAddedMillis, + DateUtils.FORMAT_ABBREV_ALL + ) .toString() } @@ -142,8 +153,13 @@ class SongListFragment : listModel.openMenu(R.menu.song, item, homeModel.playWith) } - private fun updateSongs(songs: List) { + private fun updateSongs(songs: List, indexingState: IndexingState?) { + requireBinding().apply { + homeRecycler.isInvisible = indexingState is IndexingState.Indexing || songs.isEmpty() + homeNoMusic.isInvisible = songs.isEmpty() + } songAdapter.update(songs, homeModel.songInstructions.consume()) + } private fun updateSelection(selection: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt index 77b513973..acd985780 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt @@ -120,9 +120,7 @@ constructor( // TODO: Differentiate "hard reloads" (Need the cache) and "Soft reloads" // (just need to manipulate data) when (key) { - getString(R.string.set_key_exclude_non_music), - getString(R.string.set_key_music_dirs), - getString(R.string.set_key_music_dirs_include), + getString(R.string.set_key_music_locations), getString(R.string.set_key_separators), getString(R.string.set_key_auto_sort_names) -> { L.d("Dispatching indexing setting change for $key") diff --git a/app/src/main/res/layout/fragment_home_list.xml b/app/src/main/res/layout/fragment_home_list.xml index fd9720d57..87396fac9 100644 --- a/app/src/main/res/layout/fragment_home_list.xml +++ b/app/src/main/res/layout/fragment_home_list.xml @@ -1,8 +1,52 @@ - + android:layout_height="match_parent"> + + + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/inner.xml b/app/src/main/res/navigation/inner.xml index ff6f18d10..13f90102b 100644 --- a/app/src/main/res/navigation/inner.xml +++ b/app/src/main/res/navigation/inner.xml @@ -87,6 +87,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e76c63bd6..518602a5d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ Monitoring music library Retry + Pick folders More @@ -214,6 +215,11 @@ Starts Auxio using the previously saved state. If no saved state is available, all songs will be shuffled. Playback will start immediately. \n\nWARNING: Be careful controlling this service, if you close it and then try to use it again, you will probably crash the app. + Your songs will show up here once you add some music. + Your albums will show up here once you add some music. + Your artists will show up here once you add some music. + Your genres will show up here once you add some music. + Your playlists will show up here once you add some music.