diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 0c97359d5..9500b24c7 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -58,8 +58,6 @@ class MainFragment : Fragment() { // --- VIEWMODEL SETUP --- - playbackModel.setupPlayback(requireContext()) - // Change CompactPlaybackFragment's visibility here so that an animation occurs. binding.mainPlayback.isVisible = playbackModel.song.value != null 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 13b05e040..5a98d59a2 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -78,23 +78,28 @@ class DetailViewModel : ViewModel() { private var currentMenuContext: DisplayMode? = null - private val musicStore = MusicStore.getInstance() private val settingsManager = SettingsManager.getInstance() fun setGenre(id: Long, context: Context) { if (mCurGenre.value?.id == id) return + + val musicStore = MusicStore.requireInstance() mCurGenre.value = musicStore.genres.find { it.id == id } refreshGenreData(context) } fun setArtist(id: Long, context: Context) { if (mCurArtist.value?.id == id) return + + val musicStore = MusicStore.requireInstance() mCurArtist.value = musicStore.artists.find { it.id == id } refreshArtistData(context) } fun setAlbum(id: Long, context: Context) { if (mCurAlbum.value?.id == id) return + + val musicStore = MusicStore.requireInstance() mCurAlbum.value = musicStore.albums.find { it.id == id } refreshAlbumData(context) } 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 0cf230e62..82248458c 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -18,12 +18,16 @@ package org.oxycblt.auxio.home +import android.Manifest import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.widget.Button +import androidx.activity.result.contract.ActivityResultContracts import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.content.res.ResourcesCompat import androidx.core.view.iterator import androidx.core.view.updatePadding import androidx.core.view.updatePaddingRelative @@ -34,6 +38,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayoutMediator import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R @@ -46,6 +51,7 @@ import org.oxycblt.auxio.home.list.SongListFragment import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.DisplayMode @@ -73,6 +79,13 @@ class HomeFragment : Fragment() { var bottomPadding = 0 val sortItem: MenuItem + // Build the permission launcher here as you can only do it in onCreateView/onCreate + val permLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { + homeModel.reloadMusic(requireContext()) + } + // --- UI SETUP --- binding.lifecycleOwner = viewLifecycleOwner @@ -193,22 +206,96 @@ class HomeFragment : Fragment() { registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) = homeModel.updateCurrentTab(position) }) + + TabLayoutMediator(binding.homeTabs, this) { tab, pos -> + tab.setText(homeModel.tabs[pos].string) + }.attach() } binding.homeFab.setOnClickListener { playbackModel.shuffleAll() } - TabLayoutMediator(binding.homeTabs, binding.homePager) { tab, pos -> - tab.setText(homeModel.tabs[pos].string) - }.attach() - // --- VIEWMODEL SETUP --- + // Initialize music loading. Unlike MainFragment, we can not only do this here on startup + // but also show a SnackBar in a reasonable place in this fragment. + homeModel.loadMusic(requireContext()) + // There is no way a fast scrolling event can continue across a re-create. Reset it. homeModel.updateFastScrolling(false) + homeModel.loaderResponse.observe(viewLifecycleOwner) { response -> + // Handle the loader response. + when (response) { + is MusicStore.Response.Ok -> { + logD("Received Ok") + + binding.homeFab.show() + playbackModel.setupPlayback(requireContext()) + } + + is MusicStore.Response.Err -> { + logD("Received Error") + + // We received an error. Hide the FAB and show a Snackbar with the error + // message and a corresponding action + binding.homeFab.hide() + + val errorRes = when (response.kind) { + MusicStore.ErrorKind.NO_MUSIC -> R.string.err_no_music + MusicStore.ErrorKind.NO_PERMS -> R.string.err_no_perms + MusicStore.ErrorKind.FAILED -> R.string.err_load_failed + } + + val snackbar = Snackbar.make( + binding.root, getString(errorRes), Snackbar.LENGTH_INDEFINITE + ) + + snackbar.view.apply { + // Change the font family to our semibold color + findViewById