diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 5a32fbb8c..5a8644bae 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -49,6 +49,8 @@ class MainFragment : Fragment() { // --- VIEWMODEL SETUP --- + playbackModel.setupPlayback(requireContext()) + // Change CompactPlaybackFragment's visibility here so that an animation occurs. handleCompactPlaybackVisibility(binding, playbackModel.song.value) diff --git a/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt b/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt index b617ff1df..1a1d5e2d5 100644 --- a/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt @@ -29,7 +29,7 @@ import org.oxycblt.auxio.databinding.DialogAccentBinding import org.oxycblt.auxio.logD import org.oxycblt.auxio.resolveColor import org.oxycblt.auxio.settings.SettingsManager -import org.oxycblt.auxio.settings.ui.LifecycleDialog +import org.oxycblt.auxio.ui.LifecycleDialog /** * Dialog responsible for showing the list of accents to select. 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 9685761b9..c71a05191 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -31,6 +31,7 @@ import org.oxycblt.auxio.settings.SettingsManager /** * ViewModel that stores data for the [DetailFragment]s, such as what they're showing & what * [SortMode] they are currently on. + * TODO: Redo sorting here * @author OxygenCobalt */ class DetailViewModel : ViewModel() { diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt index 9bcb25c65..5932e9116 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt @@ -36,8 +36,8 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogExcludedBinding import org.oxycblt.auxio.logD import org.oxycblt.auxio.playback.PlaybackViewModel -import org.oxycblt.auxio.settings.ui.LifecycleDialog import org.oxycblt.auxio.showToast +import org.oxycblt.auxio.ui.LifecycleDialog import kotlin.system.exitProcess /** 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 410bf3f55..9034540f9 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -46,8 +46,11 @@ import org.oxycblt.auxio.recycler.DisplayMode * The main "Launching Point" fragment of Auxio, allowing navigation to the detail * views for each respective fragment. * TODO: Re-add sorting (but new and improved) + * It will require a new SortMode to be made simply for compat. Migrate the old SortMode + * eventually. * TODO: Add lift-on-scroll eventually [when I can file a bug report or hack it into working] - * FIXME: Keep the collapsed state in the ViewModel so we can make sure it stays consistent + * FIXME: Find a way to store the collapsed state so it stays consistent + * TODO: Fix issue where TabLayout ripples will shove above the indicator * @author OxygenCobalt */ class HomeFragment : Fragment() { @@ -93,7 +96,6 @@ class HomeFragment : Fragment() { // internal recyclerview and change the touch slope so that touch actions will // act more as a scroll than as a swipe. // Derived from: https://al-e-shevelev.medium.com/how-to-reduce-scroll-sensitivity-of-viewpager2-widget-87797ad02414 - try { val recycler = ViewPager2::class.java.getDeclaredField("mRecyclerView").run { isAccessible = true @@ -125,8 +127,6 @@ class HomeFragment : Fragment() { // --- VIEWMODEL SETUP --- - playbackModel.setupPlayback(requireContext()) - detailModel.navToItem.observe(viewLifecycleOwner) { item -> when (item) { is Song -> findNavController().navigate( diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt index 29dde76d8..2216a08f0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt @@ -35,6 +35,7 @@ import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.recycler.DisplayMode +import org.oxycblt.auxio.recycler.sliceArticle import org.oxycblt.auxio.spans import org.oxycblt.auxio.ui.newMenu @@ -103,7 +104,13 @@ class HomeListFragment : Fragment() { homeAdapter.updateData(toObserve.value!!) toObserve.observe(viewLifecycleOwner) { data -> - homeAdapter.updateData(data) + homeAdapter.updateData( + data.sortedWith( + compareBy(String.CASE_INSENSITIVE_ORDER) { + it.name.sliceArticle() + } + ) + ) } logD("Fragment created") diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt index 2a2093997..51885eb1b 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt @@ -18,8 +18,11 @@ package org.oxycblt.auxio.playback.queue +import android.graphics.Canvas +import android.view.animation.AccelerateDecelerateInterpolator import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView +import org.oxycblt.auxio.R import org.oxycblt.auxio.playback.PlaybackViewModel import kotlin.math.abs import kotlin.math.max @@ -30,14 +33,10 @@ import kotlin.math.sign * The Drag callback used by the queue recyclerview. Delivers updates to [PlaybackViewModel] * and [QueueAdapter] simultaneously. * @author OxygenCobalt - * TODO: Its possible to apply some elevation to the item views when they are picked up, - * however you need to keep track of the viewholder in the item touch helper and reset - * it when done. Theoretically this also means you can do the material drawer thing where - * the bottom of the recyclerview a darker color but is only shown when an item is moved. - * Maybe. */ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() { private lateinit var queueAdapter: QueueAdapter + private var shouldLift = true override fun getMovementFlags( recyclerView: RecyclerView, @@ -87,6 +86,57 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc ) } + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean + ) { + // The material design page on elevation has a cool example of draggable items elevating + // themselves when being dragged. Too bad google doesn't provide a single utility to do + // this in your own app :^). To emulate it, I check if this child is in a drag state and + // then animate an elevation change. This animation also changes the background so that + // the item will actually draw over. + + val view = viewHolder.itemView + + if (shouldLift && isCurrentlyActive && actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + view.animate() + .withStartAction { view.setBackgroundResource(R.color.surface) } + .translationZ(view.resources.getDimension(R.dimen.elevation_normal)) + .setDuration(100) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + + shouldLift = false + } + + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + } + + override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { + // When an elevated item is done, we reset the elevation using another animation + // and set the background to null again so a seam doesn't show up in further actions. + + val view = viewHolder.itemView + + if (view.translationZ != 0.0f) { + viewHolder.itemView.animate() + .withEndAction { view.setBackgroundResource(android.R.color.transparent) } + .translationZ(0.0f) + .setDuration(100) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + } + + shouldLift = true + + super.clearView(recyclerView, viewHolder) + } + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { playbackModel.removeQueueDataItem(viewHolder.bindingAdapterPosition, queueAdapter) } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt b/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt index dc93ef887..ba418516d 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt @@ -19,6 +19,7 @@ package org.oxycblt.auxio.settings.ui import androidx.appcompat.app.AlertDialog +import org.oxycblt.auxio.ui.LifecycleDialog class IntListPrefDialog(private val pref: IntListPreference) : LifecycleDialog() { override fun onConfigDialog(builder: AlertDialog.Builder) { diff --git a/app/src/main/java/org/oxycblt/auxio/settings/ui/LifecycleDialog.kt b/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/settings/ui/LifecycleDialog.kt rename to app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt index 1d6dd1bd4..7a6a39cdf 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/ui/LifecycleDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.settings.ui +package org.oxycblt.auxio.ui import android.app.Dialog import android.os.Bundle