Merge pull request #6864 from Bnyro/master

feat: support for predictive back gesture in (audio) player fragment
This commit is contained in:
Bnyro 2024-12-07 14:13:38 +01:00 committed by GitHub
commit 995335760e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 18 deletions

View File

@ -10,10 +10,14 @@ fun Fragment.setOnBackPressed(action: OnBackPressedCallback.() -> Unit): OnBackP
} }
} }
return setOnBackPressed(callback)
}
fun Fragment.setOnBackPressed(callback: OnBackPressedCallback): OnBackPressedCallback {
requireActivity().onBackPressedDispatcher.addCallback( requireActivity().onBackPressedDispatcher.addCallback(
viewLifecycleOwner, viewLifecycleOwner,
callback callback
) )
return callback return callback
} }

View File

@ -10,6 +10,8 @@ import android.text.format.DateUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.BackEventCompat
import androidx.activity.OnBackPressedCallback
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.motion.widget.TransitionAdapter import androidx.constraintlayout.motion.widget.TransitionAdapter
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
@ -240,12 +242,24 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
updateChapterIndex() updateChapterIndex()
val onBackPressedCallback = setOnBackPressed { val onBackPressedCallback = object : OnBackPressedCallback(true) {
binding.audioPlayerContainer.isClickable = false override fun handleOnBackPressed() {
binding.playerMotionLayout.transitionToEnd() binding.audioPlayerContainer.isClickable = false
mainActivity?.binding?.mainMotionLayout?.transitionToEnd() binding.playerMotionLayout.transitionToEnd()
mainActivity?.requestOrientationChange() mainActivity?.binding?.mainMotionLayout?.transitionToEnd()
mainActivity?.requestOrientationChange()
}
override fun handleOnBackProgressed(backEvent: BackEventCompat) {
binding.playerMotionLayout.progress = backEvent.progress
}
override fun handleOnBackCancelled() {
binding.playerMotionLayout.transitionToStart()
}
} }
setOnBackPressed(onBackPressedCallback)
viewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible -> viewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible ->
// if the player is minimized, the fragment behind the player should handle the event // if the player is minimized, the fragment behind the player should handle the event
onBackPressedCallback.isEnabled = isMiniPlayerVisible != true onBackPressedCallback.isEnabled = isMiniPlayerVisible != true

View File

@ -24,6 +24,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams import android.view.ViewGroup.LayoutParams
import android.widget.Toast import android.widget.Toast
import androidx.activity.BackEventCompat
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.motion.widget.TransitionAdapter import androidx.constraintlayout.motion.widget.TransitionAdapter
@ -142,9 +144,10 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
private lateinit var streams: Streams private lateinit var streams: Streams
val isShort val isShort
get() = run { get() = run {
val heightGreaterThanWidth = ::streams.isInitialized && streams.videoStreams.firstOrNull()?.let { val heightGreaterThanWidth =
(it.height ?: 0) > (it.width ?: 0) ::streams.isInitialized && streams.videoStreams.firstOrNull()?.let {
} == true (it.height ?: 0) > (it.width ?: 0)
} == true
PlayingQueue.getCurrent()?.isShort == true || heightGreaterThanWidth PlayingQueue.getCurrent()?.isShort == true || heightGreaterThanWidth
} }
@ -461,15 +464,27 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
attachToPlayerService(playerData, createNewSession) attachToPlayerService(playerData, createNewSession)
} }
val onBackPressedCallback = setOnBackPressed { val onBackPressedCallback = object : OnBackPressedCallback(true) {
if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen() override fun handleOnBackPressed() {
else { if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen()
binding.playerMotionLayout.setTransitionDuration(250) else {
binding.playerMotionLayout.transitionToEnd() binding.playerMotionLayout.setTransitionDuration(250)
mainActivity.binding.mainMotionLayout.transitionToEnd() binding.playerMotionLayout.transitionToEnd()
mainActivity.requestOrientationChange() mainActivity.binding.mainMotionLayout.transitionToEnd()
mainActivity.requestOrientationChange()
}
}
override fun handleOnBackProgressed(backEvent: BackEventCompat) {
binding.playerMotionLayout.progress = backEvent.progress
}
override fun handleOnBackCancelled() {
binding.playerMotionLayout.transitionToStart()
} }
} }
setOnBackPressed(onBackPressedCallback)
commonPlayerViewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible -> commonPlayerViewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible ->
// if the player is minimized, the fragment behind the player should handle the event // if the player is minimized, the fragment behind the player should handle the event
onBackPressedCallback.isEnabled = isMiniPlayerVisible != true onBackPressedCallback.isEnabled = isMiniPlayerVisible != true
@ -496,7 +511,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
playerController.addListener(playerListener) playerController.addListener(playerListener)
if (!startNewSession) { if (!startNewSession) {
val streams: Streams? = playerController.mediaMetadata.extras?.parcelable(IntentData.streams) val streams: Streams? =
playerController.mediaMetadata.extras?.parcelable(IntentData.streams)
// reload the streams data and playback, metadata apparently no longer exists // reload the streams data and playback, metadata apparently no longer exists
if (streams == null) { if (streams == null) {
@ -756,7 +772,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
} }
private fun playOnBackground() { private fun playOnBackground() {
val currentPosition = if (::playerController.isInitialized) playerController.currentPosition else 0 val currentPosition =
if (::playerController.isInitialized) playerController.currentPosition else 0
BackgroundHelper.playOnBackground( BackgroundHelper.playOnBackground(
requireContext(), requireContext(),