playback: eliminate old viewpager stuff

This commit is contained in:
Alexander Capehart 2023-12-16 17:49:41 -07:00
parent b0dd13b9a3
commit 4cb309f01f
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 77 additions and 63 deletions

View file

@ -29,27 +29,20 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels 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 dagger.hilt.android.AndroidEntryPoint
import java.lang.reflect.Field
import kotlin.math.abs
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.ListViewModel
import org.oxycblt.auxio.list.adapter.UpdateInstructions
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.Song 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.state.RepeatMode
import org.oxycblt.auxio.playback.ui.PlaybackPagerAdapter import org.oxycblt.auxio.playback.ui.PlaybackPagerAdapter
import org.oxycblt.auxio.playback.ui.StyledSeekBar import org.oxycblt.auxio.playback.ui.StyledSeekBar
import org.oxycblt.auxio.playback.ui.SwipeCoverView import org.oxycblt.auxio.playback.ui.SwipeCoverView
import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.lazyReflectedField
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.overrideOnOverflowMenuClick import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
@ -71,7 +64,6 @@ class PlaybackPanelFragment :
SwipeCoverView.OnSwipeListener { SwipeCoverView.OnSwipeListener {
private val playbackModel: PlaybackViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels()
private val detailModel: DetailViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels()
private val queueModel: QueueViewModel by activityViewModels()
private val listModel: ListViewModel by activityViewModels() private val listModel: ListViewModel by activityViewModels()
private var equalizerLauncher: ActivityResultLauncher<Intent>? = null private var equalizerLauncher: ActivityResultLauncher<Intent>? = null
private var coverAdapter: PlaybackPagerAdapter? = null private var coverAdapter: PlaybackPagerAdapter? = null
@ -111,15 +103,11 @@ 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
}
binding.playbackCover.onSwipeListener = this binding.playbackCover.onSwipeListener = this
binding.playbackSong.setOnClickListener { navigateToCurrentSong() }
binding.playbackArtist.setOnClickListener { navigateToCurrentArtist() }
binding.playbackAlbum.setOnClickListener { navigateToCurrentAlbum() }
binding.playbackSeekBar.listener = this binding.playbackSeekBar.listener = this
// Set up actions // Set up actions
@ -137,8 +125,6 @@ class PlaybackPanelFragment :
collectImmediately(playbackModel.repeatMode, ::updateRepeat) collectImmediately(playbackModel.repeatMode, ::updateRepeat)
collectImmediately(playbackModel.isPlaying, ::updatePlaying) collectImmediately(playbackModel.isPlaying, ::updatePlaying)
collectImmediately(playbackModel.isShuffled, ::updateShuffled) collectImmediately(playbackModel.isShuffled, ::updateShuffled)
collectImmediately(queueModel.queue, ::updateQueue)
collectImmediately(queueModel.index, ::updateQueuePosition)
} }
override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) { override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) {
@ -190,7 +176,12 @@ class PlaybackPanelFragment :
} }
val binding = requireBinding() val binding = requireBinding()
val context = requireContext()
logD("Updating song display: $song") 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() binding.playbackSeekBar.durationDs = song.durationMs.msToDs()
} }
@ -220,43 +211,15 @@ class PlaybackPanelFragment :
requireBinding().playbackShuffle.isActivated = isShuffled requireBinding().playbackShuffle.isActivated = isShuffled
} }
override fun navigateToCurrentSong() { private fun navigateToCurrentSong() {
playbackModel.song.value?.let(detailModel::showAlbum) playbackModel.song.value?.let(detailModel::showAlbum)
} }
override fun navigateToCurrentArtist() { private fun navigateToCurrentArtist() {
playbackModel.song.value?.let(detailModel::showArtist) playbackModel.song.value?.let(detailModel::showArtist)
} }
override fun navigateToCurrentAlbum() { private fun navigateToCurrentAlbum() {
playbackModel.song.value?.let { detailModel.showAlbum(it.album) } 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")
}
} }

View file

@ -22,6 +22,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -42,7 +43,7 @@ import org.oxycblt.auxio.util.logD
*/ */
@AndroidEntryPoint @AndroidEntryPoint
class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), EditClickListListener<Song> { class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), EditClickListListener<Song> {
private val queueModel: QueueViewModel by activityViewModels() private val queueModel: QueueViewModel by viewModels()
private val playbackModel: PlaybackViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels()
private val queueAdapter = QueueAdapter(this) private val queueAdapter = QueueAdapter(this)
private var touchHelper: ItemTouchHelper? = null private var touchHelper: ItemTouchHelper? = null

View file

@ -73,10 +73,7 @@ class CoverViewHolder private constructor(private val binding: ItemPlaybackSongB
val context = binding.root.context val context = binding.root.context
binding.playbackCover.bind(item) binding.playbackCover.bind(item)
// binding.playbackCover.bind(item) // binding.playbackCover.bind(item)
binding.playbackSong.apply { binding.playbackSong.apply { text = item.name.resolve(context) }
text = item.name.resolve(context)
setOnClickListener { listener.navigateToCurrentSong() }
}
binding.playbackArtist.apply { binding.playbackArtist.apply {
text = item.artists.resolveNames(context) text = item.artists.resolveNames(context)
setOnClickListener { listener.navigateToCurrentArtist() } setOnClickListener { listener.navigateToCurrentArtist() }

View file

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.oxycblt.auxio.playback.ui package org.oxycblt.auxio.playback.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
@ -77,8 +77,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
val diffX = e2.x - e1.x val diffX = e2.x - e1.x
if (abs(diffX) > abs(diffY) && if (abs(diffX) > abs(diffY) &&
abs(diffX) > viewConfig.scaledTouchSlop && abs(diffX) > viewConfig.scaledTouchSlop &&
abs(velocityX) > viewConfig.scaledMinimumFlingVelocity abs(velocityX) > viewConfig.scaledMinimumFlingVelocity) {
) {
if (diffX > 0) { if (diffX > 0) {
onSwipeRight() onSwipeRight()
} else { } else {
@ -102,6 +101,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
interface OnSwipeListener { interface OnSwipeListener {
fun onSwipePrevious() fun onSwipePrevious()
fun onSwipeNext() fun onSwipeNext()
} }
} }

View file

@ -62,7 +62,8 @@
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar" app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" /> tools:text="Album Name" />
<org.oxycblt.auxio.playback.ui.StyledSeekBar <org.oxycblt.auxio.playback.ui.StyledSeekBar
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
@ -153,4 +154,4 @@
</org.oxycblt.auxio.playback.ui.ForcedLTRFrameLayout> </org.oxycblt.auxio.playback.ui.ForcedLTRFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -44,11 +44,25 @@
android:id="@+id/playback_artist" android:id="@+id/playback_artist"
style="@style/Widget.Auxio.TextView.Secondary.Marquee" style="@style/Widget.Auxio.TextView.Secondary.Marquee"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
app:layout_constraintBottom_toTopOf="@+id/playback_album"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="Artist Name" />
<TextView
android:id="@+id/playback_album"
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar" app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" /> tools:text="Album Name" />
<org.oxycblt.auxio.playback.ui.StyledSeekBar <org.oxycblt.auxio.playback.ui.StyledSeekBar
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"

View file

@ -16,6 +16,7 @@
app:title="@string/lbl_playback" app:title="@string/lbl_playback"
tools:subtitle="@string/lbl_all_songs" /> tools:subtitle="@string/lbl_all_songs" />
<org.oxycblt.auxio.playback.ui.SwipeCoverView <org.oxycblt.auxio.playback.ui.SwipeCoverView
android:id="@+id/playback_cover" android:id="@+id/playback_cover"
style="@style/Widget.Auxio.Image.Full" style="@style/Widget.Auxio.Image.Full"
@ -24,11 +25,48 @@
app:enablePlaybackIndicator="false" app:enablePlaybackIndicator="false"
app:enableSelectionBadge="false" app:enableSelectionBadge="false"
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar" app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
app:layout_constraintVertical_chainStyle="packed" /> app:layout_constraintVertical_chainStyle="packed" />
<LinearLayout
android:id="@+id/playback_info_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toTopOf="@+id/playback_cover"
app:layout_constraintVertical_chainStyle="packed">
<TextView
android:id="@+id/playback_song"
style="@style/Widget.Auxio.TextView.Primary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Song Name" />
<TextView
android:id="@+id/playback_artist"
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Artist Name" />
<TextView
android:id="@+id/playback_album"
style="@style/Widget.Auxio.TextView.Secondary.Marquee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Album Name" />
</LinearLayout>
<org.oxycblt.auxio.playback.ui.StyledSeekBar <org.oxycblt.auxio.playback.ui.StyledSeekBar
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
android:layout_width="match_parent" android:layout_width="match_parent"