home: make no music action generic
This way the playlist view can switch to "New Playlist" if a load finishes but the user hasn't made any playlists.
This commit is contained in:
parent
0f4a550775
commit
9161b8f777
8 changed files with 65 additions and 27 deletions
|
@ -36,6 +36,8 @@ interface HomeGenerator {
|
||||||
|
|
||||||
fun release()
|
fun release()
|
||||||
|
|
||||||
|
fun empty(): Boolean
|
||||||
|
|
||||||
fun songs(): List<Song>
|
fun songs(): List<Song>
|
||||||
|
|
||||||
fun albums(): List<Album>
|
fun albums(): List<Album>
|
||||||
|
@ -49,6 +51,8 @@ interface HomeGenerator {
|
||||||
fun tabs(): List<MusicType>
|
fun tabs(): List<MusicType>
|
||||||
|
|
||||||
interface Invalidator {
|
interface Invalidator {
|
||||||
|
fun invalidateEmpty() {}
|
||||||
|
|
||||||
fun invalidateMusic(type: MusicType, instructions: UpdateInstructions)
|
fun invalidateMusic(type: MusicType, instructions: UpdateInstructions)
|
||||||
|
|
||||||
fun invalidateTabs()
|
fun invalidateTabs()
|
||||||
|
@ -119,6 +123,8 @@ private class HomeGeneratorImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
||||||
|
invalidator.invalidateEmpty()
|
||||||
|
|
||||||
val library = musicRepository.library
|
val library = musicRepository.library
|
||||||
if (changes.deviceLibrary && library != null) {
|
if (changes.deviceLibrary && library != null) {
|
||||||
L.d("Refreshing library")
|
L.d("Refreshing library")
|
||||||
|
@ -142,6 +148,9 @@ private class HomeGeneratorImpl(
|
||||||
homeSettings.unregisterListener(this)
|
homeSettings.unregisterListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun empty() =
|
||||||
|
musicRepository.library == null
|
||||||
|
|
||||||
override fun songs() =
|
override fun songs() =
|
||||||
musicRepository.library?.let { listSettings.songSort.songs(it.songs) } ?: emptyList()
|
musicRepository.library?.let { listSettings.songSort.songs(it.songs) } ?: emptyList()
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,10 @@ constructor(
|
||||||
val playlistList: StateFlow<List<Playlist>>
|
val playlistList: StateFlow<List<Playlist>>
|
||||||
get() = _playlistList
|
get() = _playlistList
|
||||||
|
|
||||||
|
private val _empty = MutableStateFlow(false)
|
||||||
|
val empty: StateFlow<Boolean>
|
||||||
|
get() = _empty
|
||||||
|
|
||||||
private val _playlistInstructions = MutableEvent<UpdateInstructions>()
|
private val _playlistInstructions = MutableEvent<UpdateInstructions>()
|
||||||
/** Instructions for how to update [genreList] in the UI. */
|
/** Instructions for how to update [genreList] in the UI. */
|
||||||
val playlistInstructions: Event<UpdateInstructions>
|
val playlistInstructions: Event<UpdateInstructions>
|
||||||
|
@ -129,6 +133,7 @@ constructor(
|
||||||
val playlistSort: Sort
|
val playlistSort: Sort
|
||||||
get() = listSettings.playlistSort
|
get() = listSettings.playlistSort
|
||||||
|
|
||||||
|
|
||||||
private val homeGenerator = homeGeneratorFactory.create(this)
|
private val homeGenerator = homeGeneratorFactory.create(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,6 +177,10 @@ constructor(
|
||||||
homeGenerator.release()
|
homeGenerator.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun invalidateEmpty() {
|
||||||
|
_empty.value = homeGenerator.empty()
|
||||||
|
}
|
||||||
|
|
||||||
override fun invalidateMusic(type: MusicType, instructions: UpdateInstructions) {
|
override fun invalidateMusic(type: MusicType, instructions: UpdateInstructions) {
|
||||||
when (type) {
|
when (type) {
|
||||||
MusicType.SONGS -> {
|
MusicType.SONGS -> {
|
||||||
|
|
|
@ -87,9 +87,10 @@ class AlbumListFragment :
|
||||||
}
|
}
|
||||||
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_albums)
|
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_albums)
|
||||||
|
|
||||||
binding.homeChooseMusicSources.setOnClickListener { homeModel.startChooseMusicLocations() }
|
binding.homeNoMusicAction.setOnClickListener { homeModel.startChooseMusicLocations() }
|
||||||
|
|
||||||
collectImmediately(homeModel.albumList, ::updateAlbums)
|
collectImmediately(homeModel.albumList, ::updateAlbums)
|
||||||
|
collectImmediately(homeModel.empty, ::updateNoMusicIndicator)
|
||||||
collectImmediately(listModel.selected, ::updateSelection)
|
collectImmediately(listModel.selected, ::updateSelection)
|
||||||
collectImmediately(
|
collectImmediately(
|
||||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||||
|
@ -154,13 +155,15 @@ class AlbumListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAlbums(albums: List<Album>) {
|
private fun updateAlbums(albums: List<Album>) {
|
||||||
requireBinding().apply {
|
|
||||||
homeRecycler.isInvisible = albums.isEmpty()
|
|
||||||
homeNoMusic.isInvisible = albums.isNotEmpty()
|
|
||||||
}
|
|
||||||
albumAdapter.update(albums, homeModel.albumInstructions.consume())
|
albumAdapter.update(albums, homeModel.albumInstructions.consume())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateNoMusicIndicator(empty: Boolean) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.homeRecycler.isInvisible = empty
|
||||||
|
binding.homeNoMusic.isInvisible = !empty
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateSelection(selection: List<Music>) {
|
private fun updateSelection(selection: List<Music>) {
|
||||||
albumAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
albumAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,10 @@ class ArtistListFragment :
|
||||||
}
|
}
|
||||||
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_artists)
|
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_artists)
|
||||||
|
|
||||||
binding.homeChooseMusicSources.setOnClickListener { homeModel.startChooseMusicLocations() }
|
binding.homeNoMusicAction.setOnClickListener { homeModel.startChooseMusicLocations() }
|
||||||
|
|
||||||
collectImmediately(homeModel.artistList, ::updateArtists)
|
collectImmediately(homeModel.artistList, ::updateArtists)
|
||||||
|
collectImmediately(homeModel.empty, ::updateNoMusicIndicator)
|
||||||
collectImmediately(listModel.selected, ::updateSelection)
|
collectImmediately(listModel.selected, ::updateSelection)
|
||||||
collectImmediately(
|
collectImmediately(
|
||||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||||
|
@ -129,13 +130,15 @@ class ArtistListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateArtists(artists: List<Artist>) {
|
private fun updateArtists(artists: List<Artist>) {
|
||||||
requireBinding().apply {
|
|
||||||
homeRecycler.isInvisible = artists.isEmpty()
|
|
||||||
homeNoMusic.isInvisible = artists.isNotEmpty()
|
|
||||||
}
|
|
||||||
artistAdapter.update(artists, homeModel.artistInstructions.consume())
|
artistAdapter.update(artists, homeModel.artistInstructions.consume())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateNoMusicIndicator(empty: Boolean) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.homeRecycler.isInvisible = empty
|
||||||
|
binding.homeNoMusic.isInvisible = !empty
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateSelection(selection: List<Music>) {
|
private fun updateSelection(selection: List<Music>) {
|
||||||
artistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
artistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,9 +80,10 @@ class GenreListFragment :
|
||||||
}
|
}
|
||||||
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_genres)
|
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_genres)
|
||||||
|
|
||||||
binding.homeChooseMusicSources.setOnClickListener { homeModel.startChooseMusicLocations() }
|
binding.homeNoMusicAction.setOnClickListener { homeModel.startChooseMusicLocations() }
|
||||||
|
|
||||||
collectImmediately(homeModel.genreList, ::updateGenres)
|
collectImmediately(homeModel.genreList, ::updateGenres)
|
||||||
|
collectImmediately(homeModel.empty, ::updateNoMusicIndicator)
|
||||||
collectImmediately(listModel.selected, ::updateSelection)
|
collectImmediately(listModel.selected, ::updateSelection)
|
||||||
collectImmediately(
|
collectImmediately(
|
||||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||||
|
@ -128,13 +129,15 @@ class GenreListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGenres(genres: List<Genre>) {
|
private fun updateGenres(genres: List<Genre>) {
|
||||||
requireBinding().apply {
|
|
||||||
homeRecycler.isInvisible = genres.isEmpty()
|
|
||||||
homeNoMusic.isInvisible = genres.isNotEmpty()
|
|
||||||
}
|
|
||||||
genreAdapter.update(genres, homeModel.genreInstructions.consume())
|
genreAdapter.update(genres, homeModel.genreInstructions.consume())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateNoMusicIndicator(empty: Boolean) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.homeRecycler.isInvisible = empty
|
||||||
|
binding.homeNoMusic.isInvisible = !empty
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateSelection(selection: List<Music>) {
|
private fun updateSelection(selection: List<Music>) {
|
||||||
genreAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
genreAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,9 +78,8 @@ class PlaylistListFragment :
|
||||||
}
|
}
|
||||||
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_playlists)
|
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_playlists)
|
||||||
|
|
||||||
binding.homeChooseMusicSources.setOnClickListener { homeModel.startChooseMusicLocations() }
|
|
||||||
|
|
||||||
collectImmediately(homeModel.playlistList, ::updatePlaylists)
|
collectImmediately(homeModel.playlistList, ::updatePlaylists)
|
||||||
|
collectImmediately(homeModel.empty, homeModel.playlistList, ::updateNoMusicIndicator)
|
||||||
collectImmediately(listModel.selected, ::updateSelection)
|
collectImmediately(listModel.selected, ::updateSelection)
|
||||||
collectImmediately(
|
collectImmediately(
|
||||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||||
|
@ -126,13 +125,22 @@ class PlaylistListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlaylists(playlists: List<Playlist>) {
|
private fun updatePlaylists(playlists: List<Playlist>) {
|
||||||
requireBinding().apply {
|
|
||||||
homeRecycler.isInvisible = playlists.isEmpty()
|
|
||||||
homeNoMusic.isInvisible = playlists.isNotEmpty()
|
|
||||||
}
|
|
||||||
playlistAdapter.update(playlists, homeModel.playlistInstructions.consume())
|
playlistAdapter.update(playlists, homeModel.playlistInstructions.consume())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateNoMusicIndicator(empty: Boolean, playlists: List<Playlist>) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.homeRecycler.isInvisible = empty
|
||||||
|
binding.homeNoMusic.isInvisible = !empty && playlists.isNotEmpty()
|
||||||
|
if (!empty && playlists.isEmpty()) {
|
||||||
|
binding.homeNoMusicAction.text = getString(R.string.lbl_new_playlist)
|
||||||
|
binding.homeNoMusicAction.setOnClickListener { musicModel.createPlaylist() }
|
||||||
|
} else {
|
||||||
|
binding.homeNoMusicAction.text = getString(R.string.lbl_music_sources)
|
||||||
|
binding.homeNoMusicAction.setOnClickListener { homeModel.startChooseMusicLocations() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateSelection(selection: List<Music>) {
|
private fun updateSelection(selection: List<Music>) {
|
||||||
playlistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
playlistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,9 +85,10 @@ class SongListFragment :
|
||||||
}
|
}
|
||||||
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_songs)
|
binding.homeNoMusicMsg.text = getString(R.string.lng_empty_songs)
|
||||||
|
|
||||||
binding.homeChooseMusicSources.setOnClickListener { homeModel.startChooseMusicLocations() }
|
binding.homeNoMusicAction.setOnClickListener { homeModel.startChooseMusicLocations() }
|
||||||
|
|
||||||
collectImmediately(homeModel.songList, ::updateSongs)
|
collectImmediately(homeModel.songList, ::updateSongs)
|
||||||
|
collectImmediately(homeModel.empty, ::updateNoMusicIndicator)
|
||||||
collectImmediately(listModel.selected, ::updateSelection)
|
collectImmediately(listModel.selected, ::updateSelection)
|
||||||
collectImmediately(
|
collectImmediately(
|
||||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||||
|
@ -154,13 +155,15 @@ class SongListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSongs(songs: List<Song>) {
|
private fun updateSongs(songs: List<Song>) {
|
||||||
requireBinding().apply {
|
|
||||||
homeRecycler.isInvisible = songs.isEmpty()
|
|
||||||
homeNoMusic.isInvisible = songs.isNotEmpty()
|
|
||||||
}
|
|
||||||
songAdapter.update(songs, homeModel.songInstructions.consume())
|
songAdapter.update(songs, homeModel.songInstructions.consume())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateNoMusicIndicator(empty: Boolean) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.homeRecycler.isInvisible = empty
|
||||||
|
binding.homeNoMusic.isInvisible = !empty
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateSelection(selection: List<Music>) {
|
private fun updateSelection(selection: List<Music>) {
|
||||||
songAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
songAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
||||||
android:id="@+id/home_choose_music_sources"
|
android:id="@+id/home_no_music_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/lbl_music_sources" />
|
android:text="@string/lbl_music_sources" />
|
||||||
|
|
Loading…
Reference in a new issue