From 761dab92390f8f0eb38f96dc8b237e0f26a24d48 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Thu, 15 Dec 2022 13:59:40 -0700 Subject: [PATCH] ui: split off selection from home Split off selection functionality from the home fragment to a new selection viewmodel. It's going to be used elsewhere, so may as well. --- README.md | 2 +- .../auxio/detail/recycler/DetailAdapter.kt | 2 +- .../org/oxycblt/auxio/home/HomeViewModel.kt | 17 ------------ .../auxio/home/list/AlbumListFragment.kt | 2 +- .../auxio/home/list/ArtistListFragment.kt | 2 +- .../auxio/home/list/GenreListFragment.kt | 2 +- .../auxio/home/list/HomeListFragment.kt | 7 +++-- .../auxio/home/list/SongListFragment.kt | 2 +- .../oxycblt/auxio/ui/SelectionViewModel.kt | 26 +++++++++++++++++++ .../main/res/layout-h600dp/item_detail.xml | 2 +- app/src/main/res/layout-land/item_detail.xml | 2 +- .../main/res/layout-sw600dp/item_detail.xml | 2 +- .../main/res/layout-sw840dp/item_detail.xml | 2 +- app/src/main/res/layout/item_detail.xml | 2 +- 14 files changed, 42 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/ui/SelectionViewModel.kt diff --git a/README.md b/README.md index a2ad9d0ae..eaf807e32 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ I primarily built Auxio for myself, but you can use it too, I guess. - Customizable behavior - Seamless artist system that unifies album artist and artist tags - Advanced media indexer with support for multiple artists, release types, -precise/original dates, sort tags, and more + precise/original dates, sort tags, and more - SD Card-aware folder management - Reliable playback state persistence - Full ReplayGain support (On MP3, MP4, FLAC, OGG, and OPUS) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt index 9bb8c626b..c3fb3896b 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt @@ -59,7 +59,7 @@ abstract class DetailAdapter( } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) = - throw IllegalStateException() + throw NotImplementedError() override fun onBindViewHolder( holder: RecyclerView.ViewHolder, 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 2ac9d6d41..5c6178b16 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -60,10 +60,6 @@ class HomeViewModel(application: Application) : val genres: StateFlow> get() = _genres - private val _selected = MutableStateFlow(listOf()) - val selected: StateFlow> - get() = _selected - var tabs: List = visibleTabs private set @@ -88,19 +84,6 @@ class HomeViewModel(application: Application) : musicStore.addCallback(this) } - /** Select a music item. */ - fun select(item: Music) { - val items = _selected.value.toMutableList() - if (items.remove(item)) { - logD("Unselecting item $item") - _selected.value = items - } else { - logD("Selecting item $item") - items.add(item) - _selected.value = items - } - } - /** Update the current tab based off of the new ViewPager position. */ fun updateCurrentTab(pos: Int) { logD("Updating current tab to ${tabs[pos]}") 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 873b4b336..cf5808cb3 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 @@ -56,7 +56,7 @@ class AlbumListFragment : HomeListFragment() { } collectImmediately(homeModel.albums, homeAdapter::replaceList) - collectImmediately(homeModel.selected, homeAdapter::updateSelection) + collectImmediately(selectionModel.selected, homeAdapter::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handleParent) } 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 a2ec85fbc..8381fc7f8 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 @@ -52,7 +52,7 @@ class ArtistListFragment : HomeListFragment() { } collectImmediately(homeModel.artists, homeAdapter::replaceList) - collectImmediately(homeModel.selected, homeAdapter::updateSelection) + collectImmediately(selectionModel.selected, homeAdapter::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handleParent) } 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 b9d07f39f..9812ddf45 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 @@ -51,7 +51,7 @@ class GenreListFragment : HomeListFragment() { } collectImmediately(homeModel.genres, homeAdapter::replaceList) - collectImmediately(homeModel.selected, homeAdapter::updateSelection) + collectImmediately(selectionModel.selected, homeAdapter::updateSelection) collectImmediately(playbackModel.parent, playbackModel.isPlaying, ::handlePlayback) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt index 3194427c3..9f2892eb0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt @@ -20,9 +20,11 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.LayoutInflater import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.ui.SelectionViewModel import org.oxycblt.auxio.ui.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.ui.fragment.MenuFragment import org.oxycblt.auxio.ui.recycler.Item @@ -39,6 +41,7 @@ abstract class HomeListFragment : FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.OnFastScrollListener { protected val homeModel: HomeViewModel by androidActivityViewModels() + protected val selectionModel: SelectionViewModel by activityViewModels() override fun onCreateBinding(inflater: LayoutInflater) = FragmentHomeListBinding.inflate(inflater) @@ -69,7 +72,7 @@ abstract class HomeListFragment : override fun onItemClick(item: Item) { check(item is Music) { "Unexpected datatype: ${item::class.java}" } - if (homeModel.selected.value.isEmpty()) { + if (selectionModel.selected.value.isEmpty()) { onItemClick(item) } else { onSelect(item) @@ -78,6 +81,6 @@ abstract class HomeListFragment : override fun onSelect(item: Item) { check(item is Music) { "Unexpected datatype: ${item::class.java}" } - homeModel.select(item) + selectionModel.select(item) } } 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 60be8425a..4ebb2102b 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 @@ -59,7 +59,7 @@ class SongListFragment : HomeListFragment() { } collectImmediately(homeModel.songs, homeAdapter::replaceList) - collectImmediately(homeModel.selected, homeAdapter::updateSelection) + collectImmediately(selectionModel.selected, homeAdapter::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::handlePlayback) } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/SelectionViewModel.kt b/app/src/main/java/org/oxycblt/auxio/ui/SelectionViewModel.kt new file mode 100644 index 000000000..21b6461aa --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/ui/SelectionViewModel.kt @@ -0,0 +1,26 @@ +package org.oxycblt.auxio.ui + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.util.logD + +class SelectionViewModel : ViewModel() { + private val _selected = MutableStateFlow(listOf()) + val selected: StateFlow> + get() = _selected + + /** Select a music item. */ + fun select(item: Music) { + val items = _selected.value.toMutableList() + if (items.remove(item)) { + logD("Unselecting item $item") + _selected.value = items + } else { + logD("Selecting item $item") + items.add(item) + _selected.value = items + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout-h600dp/item_detail.xml b/app/src/main/res/layout-h600dp/item_detail.xml index 7a10c0ac9..f44e185af 100644 --- a/app/src/main/res/layout-h600dp/item_detail.xml +++ b/app/src/main/res/layout-h600dp/item_detail.xml @@ -65,7 +65,7 @@ style="@style/Widget.Auxio.Button.Secondary" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_medium" + android:layout_marginTop="@dimen/spacing_mid_medium" android:layout_marginEnd="@dimen/spacing_small" android:text="@string/lbl_play" app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button" diff --git a/app/src/main/res/layout-land/item_detail.xml b/app/src/main/res/layout-land/item_detail.xml index e95b3c9c8..e5d50f804 100644 --- a/app/src/main/res/layout-land/item_detail.xml +++ b/app/src/main/res/layout-land/item_detail.xml @@ -79,7 +79,7 @@ style="@style/Widget.Auxio.Button.Secondary" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_medium" + android:layout_marginTop="@dimen/spacing_mid_medium" android:layout_marginEnd="@dimen/spacing_small" android:text="@string/lbl_play" app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button" diff --git a/app/src/main/res/layout-sw600dp/item_detail.xml b/app/src/main/res/layout-sw600dp/item_detail.xml index 4a74dce21..6740a05d3 100644 --- a/app/src/main/res/layout-sw600dp/item_detail.xml +++ b/app/src/main/res/layout-sw600dp/item_detail.xml @@ -79,7 +79,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/spacing_medium" - android:layout_marginTop="@dimen/spacing_medium" + android:layout_marginTop="@dimen/spacing_mid_medium" android:layout_marginEnd="@dimen/spacing_small" android:text="@string/lbl_play" app:layout_constraintBottom_toBottomOf="@+id/detail_cover" diff --git a/app/src/main/res/layout-sw840dp/item_detail.xml b/app/src/main/res/layout-sw840dp/item_detail.xml index 80e01437e..a04e02e3b 100644 --- a/app/src/main/res/layout-sw840dp/item_detail.xml +++ b/app/src/main/res/layout-sw840dp/item_detail.xml @@ -75,7 +75,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/spacing_medium" - android:layout_marginTop="@dimen/spacing_medium" + android:layout_marginTop="@dimen/spacing_mid_medium" android:layout_marginEnd="@dimen/spacing_small" android:text="@string/lbl_play" app:layout_constraintBottom_toBottomOf="@+id/detail_cover" diff --git a/app/src/main/res/layout/item_detail.xml b/app/src/main/res/layout/item_detail.xml index 73f15620d..62c8b739d 100644 --- a/app/src/main/res/layout/item_detail.xml +++ b/app/src/main/res/layout/item_detail.xml @@ -68,7 +68,7 @@ style="@style/Widget.Auxio.Button.Secondary" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_medium" + android:layout_marginTop="@dimen/spacing_mid_medium" android:layout_marginEnd="@dimen/spacing_small" android:text="@string/lbl_play" app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button"