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,6 +10,10 @@ 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

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) {
override fun handleOnBackPressed() {
binding.audioPlayerContainer.isClickable = false binding.audioPlayerContainer.isClickable = false
binding.playerMotionLayout.transitionToEnd() binding.playerMotionLayout.transitionToEnd()
mainActivity?.binding?.mainMotionLayout?.transitionToEnd() mainActivity?.binding?.mainMotionLayout?.transitionToEnd()
mainActivity?.requestOrientationChange() 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,7 +144,8 @@ 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 =
::streams.isInitialized && streams.videoStreams.firstOrNull()?.let {
(it.height ?: 0) > (it.width ?: 0) (it.height ?: 0) > (it.width ?: 0)
} == true } == true
@ -461,7 +464,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
attachToPlayerService(playerData, createNewSession) attachToPlayerService(playerData, createNewSession)
} }
val onBackPressedCallback = setOnBackPressed { val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen() if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen()
else { else {
binding.playerMotionLayout.setTransitionDuration(250) binding.playerMotionLayout.setTransitionDuration(250)
@ -470,6 +474,17 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
mainActivity.requestOrientationChange() 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(),