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 c1e0278a6..39ae497f0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -145,7 +145,7 @@ class HomeFragment : // --- VIEWMODEL SETUP --- collect(homeModel.shouldRecreate, ::handleRecreate) collectImmediately(homeModel.currentTabMode, ::updateCurrentTab) - collectImmediately(homeModel.songLists, homeModel.isFastScrolling, ::updateFab) + collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab) collectImmediately(musicModel.indexerState, ::updateIndexerState) collect(navModel.exploreNavigationItem, ::handleNavigation) collectImmediately(selectionModel.selected, ::updateSelection) 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 c49fb75f1..c3168fb6d 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -22,6 +22,7 @@ import androidx.lifecycle.AndroidViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import org.oxycblt.auxio.home.tabs.Tab +import org.oxycblt.auxio.list.UpdateInstructions import org.oxycblt.auxio.music.* import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.library.Library @@ -42,13 +43,19 @@ class HomeViewModel(application: Application) : private val _songsList = MutableStateFlow(listOf()) /** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */ - val songLists: StateFlow> + val songsList: StateFlow> get() = _songsList + /** Specifies how to update [songsList] when it changes. */ + var songsListInstructions: UpdateInstructions? = null + private set private val _albumsLists = MutableStateFlow(listOf()) /** A list of [Album]s, sorted by the preferred [Sort], to be shown in the home view. */ val albumsList: StateFlow> get() = _albumsLists + /** Specifies how to update [albumsList] when it changes. */ + var albumsListInstructions: UpdateInstructions? = null + private set private val _artistsList = MutableStateFlow(listOf()) /** @@ -58,11 +65,17 @@ class HomeViewModel(application: Application) : */ val artistsList: MutableStateFlow> get() = _artistsList + /** Specifies how to update [artistsList] when it changes. */ + var artistsListInstructions: UpdateInstructions? = null + private set private val _genresList = MutableStateFlow(listOf()) /** A list of [Genre]s, sorted by the preferred [Sort], to be shown in the home view. */ val genresList: StateFlow> get() = _genresList + /** Specifies how to update [genresList] when it changes. */ + var genresListInstructions: UpdateInstructions? = null + private set /** The [MusicMode] to use when playing a [Song] from the UI. */ val playbackMode: MusicMode @@ -107,8 +120,11 @@ class HomeViewModel(application: Application) : logD("Library changed, refreshing library") // Get the each list of items in the library to use as our list data. // Applying the preferred sorting to them. + songsListInstructions = UpdateInstructions.DIFF _songsList.value = musicSettings.songSort.songs(library.songs) + albumsListInstructions = UpdateInstructions.DIFF _albumsLists.value = musicSettings.albumSort.albums(library.albums) + artistsListInstructions = UpdateInstructions.DIFF _artistsList.value = musicSettings.artistSort.artists( if (homeSettings.shouldHideCollaborators) { @@ -117,6 +133,7 @@ class HomeViewModel(application: Application) : } else { library.artists }) + genresListInstructions = UpdateInstructions.DIFF _genresList.value = musicSettings.genreSort.genres(library.genres) } } @@ -133,23 +150,6 @@ class HomeViewModel(application: Application) : onLibraryChanged(musicStore.library) } - /** - * Update [currentTabMode] to reflect a new ViewPager2 position - * @param pagerPos The new position of the ViewPager2 instance. - */ - fun synchronizeTabPosition(pagerPos: Int) { - logD("Updating current tab to ${currentTabModes[pagerPos]}") - _currentTabMode.value = currentTabModes[pagerPos] - } - - /** - * Mark the recreation process as complete. - * @see shouldRecreate - */ - fun finishRecreate() { - _shouldRecreate.value = false - } - /** * Get the preferred [Sort] for a given [Tab]. * @param tabMode The [MusicMode] of the [Tab] desired. @@ -173,23 +173,70 @@ class HomeViewModel(application: Application) : when (_currentTabMode.value) { MusicMode.SONGS -> { musicSettings.songSort = sort + songsListInstructions = UpdateInstructions.REPLACE _songsList.value = sort.songs(_songsList.value) } MusicMode.ALBUMS -> { musicSettings.albumSort = sort + albumsListInstructions = UpdateInstructions.REPLACE _albumsLists.value = sort.albums(_albumsLists.value) } MusicMode.ARTISTS -> { musicSettings.artistSort = sort + artistsListInstructions = UpdateInstructions.REPLACE _artistsList.value = sort.artists(_artistsList.value) } MusicMode.GENRES -> { musicSettings.genreSort = sort + genresListInstructions = UpdateInstructions.REPLACE _genresList.value = sort.genres(_genresList.value) } } } + /** Signal that the specified [UpdateInstructions] in [songsListInstructions] were performed. */ + fun finishSongsListInstructions() { + songsListInstructions = null + } + + /** + * Signal that the specified [UpdateInstructions] in [albumsListInstructions] were performed. + */ + fun finishAlbumsListInstructions() { + albumsListInstructions = null + } + + /** + * Signal that the specified [UpdateInstructions] in [artistsListInstructions] were performed. + */ + fun finishArtistsListInstructions() { + artistsListInstructions = null + } + + /** + * Signal that the specified [UpdateInstructions] in [genresListInstructions] were performed. + */ + fun finishGenresListInstructions() { + genresListInstructions = null + } + + /** + * Update [currentTabMode] to reflect a new ViewPager2 position + * @param pagerPos The new position of the ViewPager2 instance. + */ + fun synchronizeTabPosition(pagerPos: Int) { + logD("Updating current tab to ${currentTabModes[pagerPos]}") + _currentTabMode.value = currentTabModes[pagerPos] + } + + /** + * Mark the recreation process as complete. + * @see shouldRecreate + */ + fun finishRecreate() { + _shouldRecreate.value = false + } + /** * Update whether the user is fast scrolling or not in the home view. * @param isFastScrolling true if the user is currently fast scrolling, false otherwise. 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 e8911eea4..be30f78da 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 @@ -66,7 +66,7 @@ class AlbumListFragment : listener = this@AlbumListFragment } - collectImmediately(homeModel.albumsList, albumAdapter::replaceList) + collectImmediately(homeModel.albumsList, ::updateList) collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -130,6 +130,11 @@ class AlbumListFragment : openMusicMenu(anchor, R.menu.menu_album_actions, item) } + private fun updateList(albums: List) { + albumAdapter.submitList(albums, homeModel.albumsListInstructions ?: UpdateInstructions.DIFF) + homeModel.finishAlbumsListInstructions() + } + private fun updateSelection(selection: List) { albumAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf())) } 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 278f0d835..4bdd0728a 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 @@ -64,7 +64,7 @@ class ArtistListFragment : listener = this@ArtistListFragment } - collectImmediately(homeModel.artistsList, artistAdapter::replaceList) + collectImmediately(homeModel.artistsList, ::updateList) collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -108,6 +108,12 @@ class ArtistListFragment : openMusicMenu(anchor, R.menu.menu_artist_actions, item) } + private fun updateList(artists: List) { + artistAdapter.submitList( + artists, homeModel.artistsListInstructions ?: UpdateInstructions.DIFF) + homeModel.finishArtistsListInstructions() + } + private fun updateSelection(selection: List) { artistAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf())) } 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 30109b43a..b738bcbb0 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 @@ -63,7 +63,7 @@ class GenreListFragment : listener = this@GenreListFragment } - collectImmediately(homeModel.genresList, genreAdapter::replaceList) + collectImmediately(homeModel.genresList, ::updateList) collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -107,6 +107,12 @@ class GenreListFragment : openMusicMenu(anchor, R.menu.menu_artist_actions, item) } + private fun updateList(artists: List) { + genreAdapter.submitList( + artists, homeModel.genresListInstructions ?: UpdateInstructions.DIFF) + homeModel.finishGenresListInstructions() + } + private fun updateSelection(selection: List) { genreAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf())) } 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 e0ab09b87..87f7a3407 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 @@ -69,7 +69,7 @@ class SongListFragment : listener = this@SongListFragment } - collectImmediately(homeModel.songLists, songAdapter::replaceList) + collectImmediately(homeModel.songsList, ::updateList) collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -85,7 +85,7 @@ class SongListFragment : } override fun getPopup(pos: Int): String? { - val song = homeModel.songLists.value[pos] + val song = homeModel.songsList.value[pos] // Change how we display the popup depending on the current sort mode. // Note: We don't use the more correct individual artist name here, as sorts are largely // based off the names of the parent objects and not the child objects. @@ -137,6 +137,11 @@ class SongListFragment : openMusicMenu(anchor, R.menu.menu_song_actions, item) } + private fun updateList(songs: List) { + songAdapter.submitList(songs, homeModel.songsListInstructions ?: UpdateInstructions.DIFF) + homeModel.finishSongsListInstructions() + } + private fun updateSelection(selection: List) { songAdapter.setSelected(selection.filterIsInstanceTo(mutableSetOf())) } diff --git a/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt index 3ba0fee00..de624a85d 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt @@ -18,7 +18,6 @@ package org.oxycblt.auxio.util import android.app.PendingIntent -import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.content.res.ColorStateList @@ -27,7 +26,6 @@ import android.os.Build import android.util.TypedValue import android.view.LayoutInflater import android.widget.Toast -import androidx.activity.result.ActivityResultLauncher import androidx.annotation.AttrRes import androidx.annotation.ColorRes import androidx.annotation.DimenRes