From b96d2aafc0ccbf875e32416068ea78c2b087bd91 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 7 Dec 2024 14:13:14 +0100 Subject: [PATCH] feat: support for predictive back gesture in (audio) player fragment --- .../libretube/ui/extensions/OnBackPressed.kt | 6 ++- .../ui/fragments/AudioPlayerFragment.kt | 24 ++++++++--- .../libretube/ui/fragments/PlayerFragment.kt | 41 +++++++++++++------ 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/extensions/OnBackPressed.kt b/app/src/main/java/com/github/libretube/ui/extensions/OnBackPressed.kt index cc39f1d55..cd61713ad 100644 --- a/app/src/main/java/com/github/libretube/ui/extensions/OnBackPressed.kt +++ b/app/src/main/java/com/github/libretube/ui/extensions/OnBackPressed.kt @@ -10,10 +10,14 @@ fun Fragment.setOnBackPressed(action: OnBackPressedCallback.() -> Unit): OnBackP } } + return setOnBackPressed(callback) +} + +fun Fragment.setOnBackPressed(callback: OnBackPressedCallback): OnBackPressedCallback { requireActivity().onBackPressedDispatcher.addCallback( viewLifecycleOwner, callback - ) + ) return callback } \ No newline at end of file diff --git a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt index 53ac7bf35..4af65442d 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt @@ -10,6 +10,8 @@ import android.text.format.DateUtils import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.BackEventCompat +import androidx.activity.OnBackPressedCallback import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.TransitionAdapter import androidx.core.os.bundleOf @@ -240,12 +242,24 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions { updateChapterIndex() - val onBackPressedCallback = setOnBackPressed { - binding.audioPlayerContainer.isClickable = false - binding.playerMotionLayout.transitionToEnd() - mainActivity?.binding?.mainMotionLayout?.transitionToEnd() - mainActivity?.requestOrientationChange() + val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + binding.audioPlayerContainer.isClickable = false + binding.playerMotionLayout.transitionToEnd() + 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 -> // if the player is minimized, the fragment behind the player should handle the event onBackPressedCallback.isEnabled = isMiniPlayerVisible != true diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 4103b7000..e82451773 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -24,6 +24,8 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams import android.widget.Toast +import androidx.activity.BackEventCompat +import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.TransitionAdapter @@ -142,9 +144,10 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { private lateinit var streams: Streams val isShort get() = run { - val heightGreaterThanWidth = ::streams.isInitialized && streams.videoStreams.firstOrNull()?.let { - (it.height ?: 0) > (it.width ?: 0) - } == true + val heightGreaterThanWidth = + ::streams.isInitialized && streams.videoStreams.firstOrNull()?.let { + (it.height ?: 0) > (it.width ?: 0) + } == true PlayingQueue.getCurrent()?.isShort == true || heightGreaterThanWidth } @@ -461,15 +464,27 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { attachToPlayerService(playerData, createNewSession) } - val onBackPressedCallback = setOnBackPressed { - if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen() - else { - binding.playerMotionLayout.setTransitionDuration(250) - binding.playerMotionLayout.transitionToEnd() - mainActivity.binding.mainMotionLayout.transitionToEnd() - mainActivity.requestOrientationChange() + val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen() + else { + binding.playerMotionLayout.setTransitionDuration(250) + binding.playerMotionLayout.transitionToEnd() + 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 -> // if the player is minimized, the fragment behind the player should handle the event onBackPressedCallback.isEnabled = isMiniPlayerVisible != true @@ -496,7 +511,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { playerController.addListener(playerListener) 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 if (streams == null) { @@ -756,7 +772,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { } private fun playOnBackground() { - val currentPosition = if (::playerController.isInitialized) playerController.currentPosition else 0 + val currentPosition = + if (::playerController.isInitialized) playerController.currentPosition else 0 BackgroundHelper.playOnBackground( requireContext(),