From 6fc4e00a32cd282248701829340ba75232d5f46f Mon Sep 17 00:00:00 2001 From: Maxr1998 Date: Mon, 14 Jun 2021 19:27:36 +0200 Subject: [PATCH] Move player screen lock handling to extra class --- .../jellyfin/mobile/player/PlaybackMenus.kt | 2 +- .../jellyfin/mobile/player/PlayerFragment.kt | 53 ++------------- .../mobile/player/PlayerLockScreenHelper.kt | 67 +++++++++++++++++++ 3 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/org/jellyfin/mobile/player/PlayerLockScreenHelper.kt diff --git a/app/src/main/java/org/jellyfin/mobile/player/PlaybackMenus.kt b/app/src/main/java/org/jellyfin/mobile/player/PlaybackMenus.kt index 644b2919..f05a403f 100644 --- a/app/src/main/java/org/jellyfin/mobile/player/PlaybackMenus.kt +++ b/app/src/main/java/org/jellyfin/mobile/player/PlaybackMenus.kt @@ -47,7 +47,7 @@ class PlaybackMenus( fragment.onSkipToNext() } lockScreenButton.setOnClickListener { - fragment.lockScreen() + fragment.playerLockScreenHelper.lockScreen() } audioStreamsButton.setOnClickListener { fragment.suppressControllerAutoHide(true) diff --git a/app/src/main/java/org/jellyfin/mobile/player/PlayerFragment.kt b/app/src/main/java/org/jellyfin/mobile/player/PlayerFragment.kt index f4fb7637..d7b8f33b 100644 --- a/app/src/main/java/org/jellyfin/mobile/player/PlayerFragment.kt +++ b/app/src/main/java/org/jellyfin/mobile/player/PlayerFragment.kt @@ -59,16 +59,13 @@ import org.jellyfin.mobile.utils.SmartOrientationListener import org.jellyfin.mobile.utils.dip import org.jellyfin.mobile.utils.disableFullscreen import org.jellyfin.mobile.utils.enableFullscreen -import org.jellyfin.mobile.utils.isAutoRotateOn import org.jellyfin.mobile.utils.isFullscreen -import org.jellyfin.mobile.utils.lockOrientation import org.jellyfin.mobile.utils.toast import org.jellyfin.sdk.model.api.MediaStream import org.koin.android.ext.android.inject import kotlin.math.abs class PlayerFragment : Fragment() { - private val appPreferences: AppPreferences by inject() private val viewModel: PlayerViewModel by viewModels() private var _playerBinding: FragmentPlayerBinding? = null @@ -76,7 +73,6 @@ class PlayerFragment : Fragment() { private val playerView: PlayerView get() = playerBinding.playerView private val playerOverlay: View get() = playerBinding.playerOverlay private val loadingIndicator: View get() = playerBinding.loadingIndicator - private val unlockScreenButton: ImageButton get() = playerBinding.unlockScreenButton private val gestureIndicatorOverlayLayout: LinearLayout get() = playerBinding.gestureOverlayLayout private val gestureIndicatorOverlayImage: ImageView get() = playerBinding.gestureOverlayImage private val gestureIndicatorOverlayProgress: ProgressBar get() = playerBinding.gestureOverlayProgress @@ -88,6 +84,8 @@ class PlayerFragment : Fragment() { private var playbackMenus: PlaybackMenus? = null private val audioManager: AudioManager by lazy { requireContext().getSystemService()!! } + lateinit var playerLockScreenHelper: PlayerLockScreenHelper + private val currentVideoStream: MediaStream? get() = viewModel.mediaSourceOrNull?.selectedVideoStream @@ -110,15 +108,6 @@ class PlayerFragment : Fragment() { */ private val orientationListener: OrientationEventListener by lazy { SmartOrientationListener(requireActivity()) } - /** - * Runnable that hides the unlock screen button, used by [peekUnlockButton] - */ - private val hideUnlockButtonAction = Runnable { - if (_playerBinding != null) { - unlockScreenButton.isVisible = false - } - } - /** * Runnable that hides [playerView] controller */ @@ -220,6 +209,8 @@ class PlayerFragment : Fragment() { // Set controller timeout suppressControllerAutoHide(false) + playerLockScreenHelper = PlayerLockScreenHelper(this, playerBinding, orientationListener) + // Setup gesture handling setupGestureDetector() @@ -241,12 +232,6 @@ class PlayerFragment : Fragment() { } } } - - // Handle unlock action - unlockScreenButton.setOnClickListener { - unlockScreenButton.isVisible = false - unlockScreen() - } } override fun onStart() { @@ -263,26 +248,6 @@ class PlayerFragment : Fragment() { } } - fun lockScreen() { - playerView.useController = false - orientationListener.disable() - requireActivity().lockOrientation() - peekUnlockButton() - } - - private fun unlockScreen() { - if (requireActivity().isAutoRotateOn()) { - requireActivity().requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - } - orientationListener.enable() - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !requireActivity().isInPictureInPictureMode) { - playerView.useController = true - playerView.apply { - if (!isControllerVisible) showController() - } - } - } - /** * Handle current orientation and update fullscreen state and switcher icon */ @@ -324,18 +289,12 @@ class PlayerFragment : Fragment() { playerView.controllerShowTimeoutMs = if (suppress) -1 else DEFAULT_CONTROLS_TIMEOUT_MS } - private fun peekUnlockButton() { - playerView.removeCallbacks(hideUnlockButtonAction) - unlockScreenButton.isVisible = true - playerView.postDelayed(hideUnlockButtonAction, DEFAULT_CONTROLS_TIMEOUT_MS.toLong()) - } - @SuppressLint("ClickableViewAccessibility") private fun setupGestureDetector() { // Handles taps when controls are locked val unlockDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { - peekUnlockButton() + playerLockScreenHelper.peekUnlockButton() return true } }) @@ -548,7 +507,7 @@ class PlayerFragment : Fragment() { playerView.useController = !isInPictureInPictureMode if (isInPictureInPictureMode) { playbackMenus?.dismissPlaybackInfo() - hideUnlockButtonAction.run() + playerLockScreenHelper.hideUnlockButton() } } diff --git a/app/src/main/java/org/jellyfin/mobile/player/PlayerLockScreenHelper.kt b/app/src/main/java/org/jellyfin/mobile/player/PlayerLockScreenHelper.kt new file mode 100644 index 00000000..d7d82033 --- /dev/null +++ b/app/src/main/java/org/jellyfin/mobile/player/PlayerLockScreenHelper.kt @@ -0,0 +1,67 @@ +package org.jellyfin.mobile.player + +import android.content.pm.ActivityInfo +import android.os.Build +import android.view.OrientationEventListener +import android.widget.ImageButton +import androidx.core.view.isVisible +import com.google.android.exoplayer2.ui.PlayerView +import org.jellyfin.mobile.databinding.FragmentPlayerBinding +import org.jellyfin.mobile.utils.Constants +import org.jellyfin.mobile.utils.isAutoRotateOn +import org.jellyfin.mobile.utils.lockOrientation + +class PlayerLockScreenHelper( + private val playerFragment: PlayerFragment, + private val playerBinding: FragmentPlayerBinding, + private val orientationListener: OrientationEventListener, +) { + private val playerView: PlayerView by playerBinding::playerView + private val unlockScreenButton: ImageButton by playerBinding::unlockScreenButton + + /** + * Runnable that hides the unlock screen button, used by [peekUnlockButton] + */ + private val hideUnlockButtonAction = Runnable { + hideUnlockButton() + } + + init { + // Handle unlock action + unlockScreenButton.setOnClickListener { + unlockScreen() + } + } + + fun lockScreen() { + playerView.useController = false + orientationListener.disable() + playerFragment.requireActivity().lockOrientation() + peekUnlockButton() + } + + private fun unlockScreen() { + hideUnlockButton() + val activity = playerFragment.requireActivity() + if (activity.isAutoRotateOn()) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + } + orientationListener.enable() + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !activity.isInPictureInPictureMode) { + playerView.useController = true + playerView.apply { + if (!isControllerVisible) showController() + } + } + } + + fun peekUnlockButton() { + playerView.removeCallbacks(hideUnlockButtonAction) + unlockScreenButton.isVisible = true + playerView.postDelayed(hideUnlockButtonAction, Constants.DEFAULT_CONTROLS_TIMEOUT_MS.toLong()) + } + + fun hideUnlockButton() { + unlockScreenButton.isVisible = false + } +}