mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 06:10:31 +05:30
Merge pull request #5641 from Bnyro/master
feat(player): support for keyboard navigation
This commit is contained in:
commit
ce8ed66e92
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
@ -138,12 +139,7 @@ class MainActivity : BaseActivity() {
|
||||
// new way of handling back presses
|
||||
onBackPressedDispatcher.addCallback {
|
||||
if (playerViewModel.isFullscreen.value == true) {
|
||||
supportFragmentManager.fragments.filterIsInstance<PlayerFragment>()
|
||||
.firstOrNull()
|
||||
?.let {
|
||||
it.unsetFullscreen()
|
||||
return@addCallback
|
||||
}
|
||||
runOnPlayerFragment { unsetFullscreen() }
|
||||
}
|
||||
|
||||
if (binding.mainMotionLayout.progress == 0F) {
|
||||
@ -490,9 +486,8 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
super.onUserLeaveHint()
|
||||
supportFragmentManager.fragments.forEach { fragment ->
|
||||
(fragment as? PlayerFragment)?.onUserLeaveHint()
|
||||
}
|
||||
|
||||
runOnPlayerFragment { onUserLeaveHint() }
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
@ -500,4 +495,14 @@ class MainActivity : BaseActivity() {
|
||||
this.intent = intent
|
||||
loadIntentData()
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return runOnPlayerFragment { onKeyUp(keyCode, event) } ?: false
|
||||
}
|
||||
|
||||
private fun <T> runOnPlayerFragment(action: PlayerFragment.() -> T): T? {
|
||||
return supportFragmentManager.fragments.filterIsInstance<PlayerFragment>()
|
||||
.firstOrNull()
|
||||
?.let(action)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.media.session.PlaybackState
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateUtils
|
||||
import android.view.KeyEvent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
@ -231,4 +232,8 @@ class OfflinePlayerActivity : BaseActivity() {
|
||||
|
||||
super.onUserLeaveHint()
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return binding.player.onKeyBoardAction(keyCode, event)
|
||||
}
|
||||
}
|
||||
|
@ -123,15 +123,11 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
}
|
||||
|
||||
binding.prev.setOnClickListener {
|
||||
val currentIndex = PlayingQueue.currentIndex()
|
||||
if (!PlayingQueue.hasPrev()) return@setOnClickListener
|
||||
PlayingQueue.onQueueItemSelected(currentIndex - 1)
|
||||
PlayingQueue.navigatePrev()
|
||||
}
|
||||
|
||||
binding.next.setOnClickListener {
|
||||
val currentIndex = PlayingQueue.currentIndex()
|
||||
if (!PlayingQueue.hasNext()) return@setOnClickListener
|
||||
PlayingQueue.onQueueItemSelected(currentIndex + 1)
|
||||
PlayingQueue.navigateNext()
|
||||
}
|
||||
|
||||
listOf(binding.forwardTV, binding.rewindTV).forEach {
|
||||
|
@ -15,6 +15,7 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.PowerManager
|
||||
import android.text.format.DateUtils
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -190,6 +191,10 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
override fun onBackPressed() {
|
||||
unsetFullscreen()
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||
return _binding?.player?.onKeyUp(keyCode, event) ?: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,19 +540,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
// FullScreen button trigger
|
||||
// hide fullscreen button if autorotation enabled
|
||||
playerBinding.fullscreen.setOnClickListener {
|
||||
// hide player controller
|
||||
binding.player.hideController()
|
||||
if (viewModel.isFullscreen.value == false) {
|
||||
// go to fullscreen mode
|
||||
setFullscreen()
|
||||
} else {
|
||||
// exit fullscreen mode
|
||||
unsetFullscreen()
|
||||
|
||||
// disable the fullscreen button for auto fullscreen
|
||||
// this is necessary to hide the button after an auto fullscreen for shorts
|
||||
playerBinding.fullscreen.isVisible = !PlayerHelper.autoFullscreenEnabled
|
||||
}
|
||||
toggleFullscreen()
|
||||
}
|
||||
|
||||
val updateSbImageResource = {
|
||||
@ -732,6 +725,25 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
binding.player.updateMarginsByFullscreenMode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable fullscreen depending on the current state
|
||||
*/
|
||||
fun toggleFullscreen() {
|
||||
// hide player controller
|
||||
binding.player.hideController()
|
||||
if (viewModel.isFullscreen.value == false) {
|
||||
// go to fullscreen mode
|
||||
setFullscreen()
|
||||
} else {
|
||||
// exit fullscreen mode
|
||||
unsetFullscreen()
|
||||
|
||||
// disable the fullscreen button for auto fullscreen
|
||||
// this is necessary to hide the button after an auto fullscreen for shorts
|
||||
playerBinding.fullscreen.isVisible = !PlayerHelper.autoFullscreenEnabled
|
||||
}
|
||||
}
|
||||
|
||||
private fun openOrCloseFullscreenDialog(open: Boolean) {
|
||||
val playerView = binding.player
|
||||
(playerView.parent as ViewGroup).removeView(playerView)
|
||||
@ -1690,4 +1702,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
binding.player.useController = false
|
||||
binding.player.hideController()
|
||||
}
|
||||
|
||||
fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return _binding?.player?.onKeyBoardAction(keyCode, event) ?: false
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.format.DateUtils
|
||||
import android.util.AttributeSet
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
@ -23,6 +24,7 @@ import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginStart
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.text.Cue
|
||||
@ -44,6 +46,7 @@ import com.github.libretube.extensions.seekBy
|
||||
import com.github.libretube.extensions.togglePlayPauseState
|
||||
import com.github.libretube.helpers.AudioHelper
|
||||
import com.github.libretube.helpers.BrightnessHelper
|
||||
import com.github.libretube.helpers.ContextHelper
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.helpers.WindowHelper
|
||||
@ -51,6 +54,7 @@ import com.github.libretube.obj.BottomSheetItem
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.extensions.toggleSystemBars
|
||||
import com.github.libretube.ui.extensions.trySetTooltip
|
||||
import com.github.libretube.ui.fragments.PlayerFragment
|
||||
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
||||
import com.github.libretube.ui.interfaces.PlayerOptions
|
||||
import com.github.libretube.ui.listeners.PlayerGestureController
|
||||
@ -729,6 +733,34 @@ open class CustomExoPlayerView(
|
||||
return super.onInterceptTouchEvent(ev)
|
||||
}
|
||||
|
||||
fun onKeyBoardAction(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
|
||||
player?.togglePlayPauseState()
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
|
||||
forward()
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_MEDIA_REWIND -> {
|
||||
rewind()
|
||||
}
|
||||
KeyEvent.KEYCODE_N, KeyEvent.KEYCODE_NAVIGATE_NEXT -> {
|
||||
PlayingQueue.navigateNext()
|
||||
}
|
||||
KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -> {
|
||||
PlayingQueue.navigatePrev()
|
||||
}
|
||||
KeyEvent.KEYCODE_F -> {
|
||||
val fragmentManager = ContextHelper.unwrapActivity(context).supportFragmentManager
|
||||
fragmentManager.fragments.filterIsInstance<PlayerFragment>().firstOrNull()
|
||||
?.toggleFullscreen()
|
||||
}
|
||||
else -> super.onKeyUp(keyCode, event)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
open fun minimizeOrExitPlayer() = Unit
|
||||
|
||||
open fun getWindow(): Window = activity.window
|
||||
|
@ -279,15 +279,11 @@ class NowPlayingNotification(
|
||||
private fun handlePlayerAction(action: String) {
|
||||
when (action) {
|
||||
NEXT -> {
|
||||
if (!PlayingQueue.hasNext()) return
|
||||
|
||||
PlayingQueue.onQueueItemSelected(PlayingQueue.currentIndex() + 1)
|
||||
PlayingQueue.navigateNext()
|
||||
}
|
||||
|
||||
PREV -> {
|
||||
if (!PlayingQueue.hasPrev()) return
|
||||
|
||||
PlayingQueue.onQueueItemSelected(PlayingQueue.currentIndex() - 1)
|
||||
PlayingQueue.navigatePrev()
|
||||
}
|
||||
|
||||
REWIND -> {
|
||||
|
@ -222,6 +222,18 @@ object PlayingQueue {
|
||||
}
|
||||
}
|
||||
|
||||
fun navigatePrev() {
|
||||
if (!hasPrev()) return
|
||||
|
||||
onQueueItemSelected(currentIndex() - 1)
|
||||
}
|
||||
|
||||
fun navigateNext() {
|
||||
if (!hasNext()) return
|
||||
|
||||
onQueueItemSelected(currentIndex() + 1)
|
||||
}
|
||||
|
||||
fun setOnQueueTapListener(listener: (StreamItem) -> Unit) {
|
||||
onQueueTapListener = listener
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user