From df7ec27d1cd9e89142ccb92e4417b7a7d32196a3 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Sun, 12 Nov 2023 10:00:41 -0700 Subject: [PATCH] playback: temp revert swipe to next behavior It's too buggy to be in a release currently, I have to disable it for now. --- .../auxio/playback/PlaybackPanelFragment.kt | 95 ++++---------- .../auxio/playback/ui/PlaybackPagerAdapter.kt | 124 ------------------ .../layout-h480dp/fragment_playback_panel.xml | 52 +++++++- .../res/layout-h480dp/item_playback_song.xml | 56 -------- .../fragment_playback_panel.xml | 50 ++++++- .../res/layout-sw600dp/item_playback_song.xml | 56 -------- .../res/layout/fragment_playback_panel.xml | 56 +++++++- .../main/res/layout/item_playback_song.xml | 55 -------- 8 files changed, 166 insertions(+), 378 deletions(-) delete mode 100644 app/src/main/java/org/oxycblt/auxio/playback/ui/PlaybackPagerAdapter.kt delete mode 100644 app/src/main/res/layout-h480dp/item_playback_song.xml delete mode 100644 app/src/main/res/layout-sw600dp/item_playback_song.xml delete mode 100644 app/src/main/res/layout/item_playback_song.xml diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt index 53cbbe7fb..b7228d508 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt @@ -29,26 +29,18 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.widget.Toolbar import androidx.core.view.updatePadding import androidx.fragment.app.activityViewModels -import androidx.recyclerview.widget.RecyclerView -import androidx.viewpager2.widget.ViewPager2 -import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import dagger.hilt.android.AndroidEntryPoint -import java.lang.reflect.Field -import kotlin.math.abs import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.list.ListViewModel -import org.oxycblt.auxio.list.adapter.UpdateInstructions import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.playback.queue.QueueViewModel +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.state.RepeatMode -import org.oxycblt.auxio.playback.ui.PlaybackPagerAdapter import org.oxycblt.auxio.playback.ui.StyledSeekBar import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.util.collectImmediately -import org.oxycblt.auxio.util.lazyReflectedField import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.overrideOnOverflowMenuClick import org.oxycblt.auxio.util.showToast @@ -66,14 +58,11 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat class PlaybackPanelFragment : ViewBindingFragment(), Toolbar.OnMenuItemClickListener, - StyledSeekBar.Listener, - PlaybackPagerAdapter.Listener { + StyledSeekBar.Listener { private val playbackModel: PlaybackViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() - private val queueModel: QueueViewModel by activityViewModels() private val listModel: ListViewModel by activityViewModels() private var equalizerLauncher: ActivityResultLauncher? = null - private var coverAdapter: PlaybackPagerAdapter? = null override fun onCreateBinding(inflater: LayoutInflater) = FragmentPlaybackPanelBinding.inflate(inflater) @@ -110,13 +99,19 @@ class PlaybackPanelFragment : } } - // cover carousel adapter - coverAdapter = PlaybackPagerAdapter(this) - binding.playbackCoverPager.apply { - adapter = coverAdapter - registerOnPageChangeCallback(OnCoverChangedCallback(queueModel)) - val recycler = VP_RECYCLER_FIELD.get(this@apply) as RecyclerView - recycler.isNestedScrollingEnabled = false + // Set up marquee on song information, alongside click handlers that navigate to each + // respective item. + binding.playbackSong.apply { + isSelected = true + setOnClickListener { playbackModel.song.value?.let(detailModel::showAlbum) } + } + binding.playbackArtist.apply { + isSelected = true + setOnClickListener { navigateToCurrentArtist() } + } + binding.playbackAlbum.apply { + isSelected = true + setOnClickListener { navigateToCurrentAlbum() } } binding.playbackSeekBar.listener = this @@ -136,14 +131,15 @@ class PlaybackPanelFragment : collectImmediately(playbackModel.repeatMode, ::updateRepeat) collectImmediately(playbackModel.isPlaying, ::updatePlaying) collectImmediately(playbackModel.isShuffled, ::updateShuffled) - collectImmediately(queueModel.queue, ::updateQueue) - collectImmediately(queueModel.index, ::updateQueuePosition) } override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) { equalizerLauncher = null - coverAdapter = null binding.playbackToolbar.setOnMenuItemClickListener(null) + // Marquee elements leak if they are not disabled when the views are destroyed. + binding.playbackSong.isSelected = false + binding.playbackArtist.isSelected = false + binding.playbackAlbum.isSelected = false } override fun onMenuItemClick(item: MenuItem): Boolean { @@ -174,18 +170,6 @@ class PlaybackPanelFragment : playbackModel.seekTo(positionDs) } - private fun updateQueue(queue: List) { - coverAdapter?.update(queue, UpdateInstructions.Replace(0)) - } - - private fun updateQueuePosition(position: Int) { - val pager = requireBinding().playbackCoverPager - val distance = abs(pager.currentItem - position) - if (distance != 0) { - pager.setCurrentItem(position, distance == 1) - } - } - private fun updateSong(song: Song?) { if (song == null) { // Nothing to do. @@ -193,7 +177,12 @@ class PlaybackPanelFragment : } val binding = requireBinding() + val context = requireContext() logD("Updating song display: $song") + binding.playbackCover.bind(song) + binding.playbackSong.text = song.name.resolve(context) + binding.playbackArtist.text = song.artists.resolveNames(context) + binding.playbackAlbum.text = song.album.name.resolve(context) binding.playbackSeekBar.durationDs = song.durationMs.msToDs() } @@ -223,43 +212,11 @@ class PlaybackPanelFragment : requireBinding().playbackShuffle.isActivated = isShuffled } - override fun navigateToCurrentSong() { - playbackModel.song.value?.let(detailModel::showAlbum) - } - - override fun navigateToCurrentArtist() { + private fun navigateToCurrentArtist() { playbackModel.song.value?.let(detailModel::showArtist) } - override fun navigateToCurrentAlbum() { + private fun navigateToCurrentAlbum() { playbackModel.song.value?.let { detailModel.showAlbum(it.album) } } - - override fun navigateToMenu() { - // TODO - } - - private class OnCoverChangedCallback(private val queueViewModel: QueueViewModel) : - OnPageChangeCallback() { - - private var targetPosition = RecyclerView.NO_POSITION - - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - targetPosition = position - } - - override fun onPageScrollStateChanged(state: Int) { - super.onPageScrollStateChanged(state) - if (state == ViewPager2.SCROLL_STATE_IDLE && - targetPosition != RecyclerView.NO_POSITION && - targetPosition != queueViewModel.index.value) { - queueViewModel.goto(targetPosition) - } - } - } - - private companion object { - val VP_RECYCLER_FIELD: Field by lazyReflectedField(ViewPager2::class, "mRecyclerView") - } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/ui/PlaybackPagerAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/ui/PlaybackPagerAdapter.kt deleted file mode 100644 index d0f176231..000000000 --- a/app/src/main/java/org/oxycblt/auxio/playback/ui/PlaybackPagerAdapter.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * PlaybackPagerAdapter.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.playback.ui - -import android.view.ViewGroup -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView -import kotlin.jvm.internal.Intrinsics -import org.oxycblt.auxio.databinding.ItemPlaybackSongBinding -import org.oxycblt.auxio.list.adapter.FlexibleListAdapter -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.resolveNames -import org.oxycblt.auxio.util.inflater - -/** @author Koitharu, Alexander Capehart (OxygenCobalt) */ -class PlaybackPagerAdapter(private val listener: Listener) : - FlexibleListAdapter(CoverViewHolder.DIFF_CALLBACK) { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CoverViewHolder { - return CoverViewHolder.from(parent) - } - - override fun onBindViewHolder(holder: CoverViewHolder, position: Int) { - holder.bind(getItem(position), listener) - } - - override fun onViewRecycled(holder: CoverViewHolder) { - holder.recycle() - super.onViewRecycled(holder) - } - - interface Listener { - fun navigateToCurrentArtist() - - fun navigateToCurrentAlbum() - - fun navigateToCurrentSong() - - fun navigateToMenu() - } -} - -class CoverViewHolder private constructor(private val binding: ItemPlaybackSongBinding) : - RecyclerView.ViewHolder(binding.root), DefaultLifecycleObserver { - init { - binding.root.layoutParams = - RecyclerView.LayoutParams( - RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT) - } - - /** - * Bind new data to this instance. - * - * @param item The new [Song] to bind. - */ - fun bind(item: Song, listener: PlaybackPagerAdapter.Listener) { - val context = binding.root.context - binding.playbackCover.bind(item) - // binding.playbackCover.bind(item) - binding.playbackSong.apply { - text = item.name.resolve(context) - setOnClickListener { listener.navigateToCurrentSong() } - } - binding.playbackArtist.apply { - text = item.artists.resolveNames(context) - setOnClickListener { listener.navigateToCurrentArtist() } - } - binding.playbackAlbum.apply { - text = item.album.name.resolve(context) - setOnClickListener { listener.navigateToCurrentAlbum() } - } - setSelected(true) - } - - fun recycle() { - // Marquee elements leak if they are not disabled when the views are destroyed. - // TODO: Move to TextView impl to avoid having to deal with lifecycle here - setSelected(false) - } - - private fun setSelected(value: Boolean) { - binding.playbackSong.isSelected = value - binding.playbackArtist.isSelected = value - binding.playbackAlbum.isSelected = value - } - - companion object { - /** - * Create a new instance. - * - * @param parent The parent to inflate this instance from. - * @return A new instance. - */ - fun from(parent: ViewGroup) = - CoverViewHolder(ItemPlaybackSongBinding.inflate(parent.context.inflater)) - - /** A comparator that can be used with DiffUtil. */ - val DIFF_CALLBACK = - object : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: Song, newItem: Song) = - oldItem.uid == newItem.uid - - override fun areContentsTheSame(oldItem: Song, newItem: Song): Boolean { - return Intrinsics.areEqual(oldItem, newItem) - } - } - } -} diff --git a/app/src/main/res/layout-h480dp/fragment_playback_panel.xml b/app/src/main/res/layout-h480dp/fragment_playback_panel.xml index 28f69b2b2..e68de3423 100644 --- a/app/src/main/res/layout-h480dp/fragment_playback_panel.xml +++ b/app/src/main/res/layout-h480dp/fragment_playback_panel.xml @@ -16,15 +16,55 @@ app:title="@string/lbl_playback" tools:subtitle="@string/lbl_all_songs" /> - + + + + + + + - + \ No newline at end of file diff --git a/app/src/main/res/layout-h480dp/item_playback_song.xml b/app/src/main/res/layout-h480dp/item_playback_song.xml deleted file mode 100644 index 9ce0bcf47..000000000 --- a/app/src/main/res/layout-h480dp/item_playback_song.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/fragment_playback_panel.xml b/app/src/main/res/layout-sw600dp/fragment_playback_panel.xml index b7ead10f6..eecb65e6e 100644 --- a/app/src/main/res/layout-sw600dp/fragment_playback_panel.xml +++ b/app/src/main/res/layout-sw600dp/fragment_playback_panel.xml @@ -16,14 +16,54 @@ app:title="@string/lbl_playback" tools:subtitle="@string/lbl_all_songs" /> - + + + + + + + tools:text="Album Name" /> + - + \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/item_playback_song.xml b/app/src/main/res/layout-sw600dp/item_playback_song.xml deleted file mode 100644 index 9ce0bcf47..000000000 --- a/app/src/main/res/layout-sw600dp/item_playback_song.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_playback_panel.xml b/app/src/main/res/layout/fragment_playback_panel.xml index e873722e1..857cb7545 100644 --- a/app/src/main/res/layout/fragment_playback_panel.xml +++ b/app/src/main/res/layout/fragment_playback_panel.xml @@ -16,22 +16,64 @@ app:title="@string/lbl_playback" tools:subtitle="@string/lbl_all_songs" /> - + + + + + + + + + + + + + @@ -117,4 +159,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_playback_song.xml b/app/src/main/res/layout/item_playback_song.xml deleted file mode 100644 index 3e8c0c6a1..000000000 --- a/app/src/main/res/layout/item_playback_song.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file