From 51ba72d8610725c2f409b84530409db642dc9f2e Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Wed, 27 Oct 2021 18:23:15 -0600 Subject: [PATCH] music: change loading ux Move the main loading response code to MainFragment and add a new method for other objects to be notified of the progress of the music loading process. There's probably a better way to do this, but kotlin coroutines are so complex that I don't know where I would start. This also adds some enhancements, such as the error message now showing in more parts of the app and SearchFragment now re-running the query if the MusicStore instance is loaded. --- .../java/org/oxycblt/auxio/MainFragment.kt | 66 +++++++++++++++ .../org/oxycblt/auxio/home/HomeFragment.kt | 81 ++----------------- .../org/oxycblt/auxio/home/HomeViewModel.kt | 54 +++---------- .../org/oxycblt/auxio/music/MusicStore.kt | 51 ++++++++++-- .../org/oxycblt/auxio/music/MusicViewModel.kt | 59 ++++++++++++++ .../oxycblt/auxio/search/SearchFragment.kt | 11 ++- .../oxycblt/auxio/search/SearchViewModel.kt | 49 ++++++++--- .../oxycblt/auxio/settings/AboutFragment.kt | 10 +-- .../oxycblt/auxio/widgets/WidgetProvider.kt | 4 +- app/src/main/res/xml-v31/widget_info.xml | 7 +- app/src/main/res/xml/widget_info.xml | 4 +- 11 files changed, 243 insertions(+), 153 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 9500b24c7..5dd36946b 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -18,15 +18,22 @@ package org.oxycblt.auxio +import android.Manifest import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Button +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.res.ResourcesCompat import androidx.core.view.isVisible import androidx.core.view.updatePadding import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import com.google.android.material.snackbar.Snackbar import org.oxycblt.auxio.databinding.FragmentMainBinding +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.applyEdge import org.oxycblt.auxio.util.applyMaterialDrawable @@ -38,6 +45,7 @@ import org.oxycblt.auxio.util.logD */ class MainFragment : Fragment() { private val playbackModel: PlaybackViewModel by activityViewModels() + private val musicModel: MusicViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, @@ -46,6 +54,13 @@ class MainFragment : Fragment() { ): View { val binding = FragmentMainBinding.inflate(inflater) + // Build the permission launcher here as you can only do it in onCreateView/onCreate + val permLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { + musicModel.reloadMusic(requireContext()) + } + // --- UI SETUP --- binding.lifecycleOwner = viewLifecycleOwner @@ -58,6 +73,10 @@ class MainFragment : Fragment() { // --- 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. + musicModel.loadMusic(requireContext()) + // Change CompactPlaybackFragment's visibility here so that an animation occurs. binding.mainPlayback.isVisible = playbackModel.song.value != null @@ -65,6 +84,53 @@ class MainFragment : Fragment() { binding.mainPlayback.isVisible = song != null } + // Handle the music loader response. + musicModel.loaderResponse.observe(viewLifecycleOwner) { response -> + // Handle the loader response. + when (response) { + // OK, start restoring playback now + is MusicStore.Response.Ok -> playbackModel.setupPlayback(requireContext()) + + // Error, show the error to the user + is MusicStore.Response.Err -> { + logD("Received Error") + + 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