mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 08:20:32 +05:30
Merge pull request #6789 from Bnyro/master
refactor: simplify playing queue listener handling
This commit is contained in:
commit
1665b33385
@ -0,0 +1,16 @@
|
|||||||
|
package com.github.libretube.extensions
|
||||||
|
|
||||||
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.media3.session.MediaController
|
||||||
|
import com.github.libretube.enums.PlayerCommand
|
||||||
|
import com.github.libretube.services.AbstractPlayerService
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
|
fun MediaController.navigateVideo(videoId: String) {
|
||||||
|
sendCustomCommand(
|
||||||
|
AbstractPlayerService.runPlayerActionCommand,
|
||||||
|
bundleOf(PlayerCommand.PLAY_VIDEO_BY_ID.name to videoId)
|
||||||
|
)
|
||||||
|
}
|
@ -158,15 +158,19 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.containsKey(PlayerCommand.PLAY_VIDEO_BY_ID.name) -> {
|
args.containsKey(PlayerCommand.PLAY_VIDEO_BY_ID.name) -> {
|
||||||
videoId = args.getString(PlayerCommand.PLAY_VIDEO_BY_ID.name) ?: return
|
navigateVideo(args.getString(PlayerCommand.PLAY_VIDEO_BY_ID.name) ?: return)
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
startPlayback()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun navigateVideo(videoId: String) {
|
||||||
|
this.videoId = videoId
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
startPlayback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getSubtitleRoleFlags(subtitle: Subtitle?): Int {
|
fun getSubtitleRoleFlags(subtitle: Subtitle?): Int {
|
||||||
return if (subtitle?.autoGenerated != true) {
|
return if (subtitle?.autoGenerated != true) {
|
||||||
C.ROLE_FLAG_CAPTION
|
C.ROLE_FLAG_CAPTION
|
||||||
@ -180,11 +184,11 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
|
|||||||
|
|
||||||
when (event) {
|
when (event) {
|
||||||
PlayerEvent.Next -> {
|
PlayerEvent.Next -> {
|
||||||
PlayingQueue.navigateNext()
|
navigateVideo(PlayingQueue.getNext() ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerEvent.Prev -> {
|
PlayerEvent.Prev -> {
|
||||||
PlayingQueue.navigatePrev()
|
navigateVideo(PlayingQueue.getPrev() ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerEvent.Stop -> {
|
PlayerEvent.Stop -> {
|
||||||
|
@ -14,7 +14,6 @@ import com.github.libretube.enums.FileType
|
|||||||
import com.github.libretube.extensions.serializable
|
import com.github.libretube.extensions.serializable
|
||||||
import com.github.libretube.extensions.setMetadata
|
import com.github.libretube.extensions.setMetadata
|
||||||
import com.github.libretube.extensions.toAndroidUri
|
import com.github.libretube.extensions.toAndroidUri
|
||||||
import com.github.libretube.extensions.toID
|
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
import com.github.libretube.ui.activities.MainActivity
|
import com.github.libretube.ui.activities.MainActivity
|
||||||
import com.github.libretube.ui.activities.NoInternetActivity
|
import com.github.libretube.ui.activities.NoInternetActivity
|
||||||
@ -67,10 +66,6 @@ open class OfflinePlayerService : AbstractPlayerService() {
|
|||||||
|
|
||||||
PlayingQueue.clear()
|
PlayingQueue.clear()
|
||||||
|
|
||||||
PlayingQueue.setOnQueueTapListener { streamItem ->
|
|
||||||
streamItem.url?.toID()?.let { playNextVideo(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
exoPlayer?.addListener(playerListener)
|
exoPlayer?.addListener(playerListener)
|
||||||
|
|
||||||
fillQueue()
|
fillQueue()
|
||||||
|
@ -24,7 +24,6 @@ import com.github.libretube.db.DatabaseHelper
|
|||||||
import com.github.libretube.enums.PlayerCommand
|
import com.github.libretube.enums.PlayerCommand
|
||||||
import com.github.libretube.extensions.parcelable
|
import com.github.libretube.extensions.parcelable
|
||||||
import com.github.libretube.extensions.setMetadata
|
import com.github.libretube.extensions.setMetadata
|
||||||
import com.github.libretube.extensions.toID
|
|
||||||
import com.github.libretube.extensions.toastFromMainDispatcher
|
import com.github.libretube.extensions.toastFromMainDispatcher
|
||||||
import com.github.libretube.extensions.toastFromMainThread
|
import com.github.libretube.extensions.toastFromMainThread
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
@ -113,10 +112,6 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
|
|
||||||
if (!playerData.keepQueue) PlayingQueue.clear()
|
if (!playerData.keepQueue) PlayingQueue.clear()
|
||||||
|
|
||||||
PlayingQueue.setOnQueueTapListener { streamItem ->
|
|
||||||
streamItem.url?.toID()?.let { playNextVideo(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
exoPlayer?.addListener(playerListener)
|
exoPlayer?.addListener(playerListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ import com.github.libretube.helpers.ThemeHelper
|
|||||||
import com.github.libretube.ui.viewholders.PlayingQueueViewHolder
|
import com.github.libretube.ui.viewholders.PlayingQueueViewHolder
|
||||||
import com.github.libretube.util.PlayingQueue
|
import com.github.libretube.util.PlayingQueue
|
||||||
|
|
||||||
class PlayingQueueAdapter : RecyclerView.Adapter<PlayingQueueViewHolder>() {
|
class PlayingQueueAdapter(
|
||||||
|
private val onQueueItemSelected: (String) -> Unit
|
||||||
|
) : RecyclerView.Adapter<PlayingQueueViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlayingQueueViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlayingQueueViewHolder {
|
||||||
val binding = QueueRowBinding.inflate(
|
val binding = QueueRowBinding.inflate(
|
||||||
@ -45,14 +47,17 @@ class PlayingQueueAdapter : RecyclerView.Adapter<PlayingQueueViewHolder>() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
|
val newVideoId = streamItem.url?.toID() ?: return@setOnClickListener
|
||||||
|
|
||||||
val oldPosition = PlayingQueue.currentIndex()
|
val oldPosition = PlayingQueue.currentIndex()
|
||||||
// get the new position from the queue to work properly after reordering the queue
|
// get the new position from the queue to work properly after reordering the queue
|
||||||
val newPosition = PlayingQueue.getStreams().indexOfFirst {
|
val newPosition = PlayingQueue.getStreams().indexOfFirst {
|
||||||
it.url?.toID() == streamItem.url?.toID()
|
it.url?.toID() == newVideoId
|
||||||
}.takeIf { it >= 0 } ?: return@setOnClickListener
|
}.takeIf { it >= 0 } ?: return@setOnClickListener
|
||||||
|
PlayingQueue.updateCurrent(streamItem)
|
||||||
|
|
||||||
// select the new item in the queue and update the selected item in the UI
|
// select the new item in the queue and update the selected item in the UI
|
||||||
PlayingQueue.onQueueItemSelected(newPosition)
|
onQueueItemSelected(newVideoId)
|
||||||
notifyItemChanged(oldPosition)
|
notifyItemChanged(oldPosition)
|
||||||
notifyItemChanged(newPosition)
|
notifyItemChanged(newPosition)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import com.github.libretube.R
|
|||||||
import com.github.libretube.api.obj.ChapterSegment
|
import com.github.libretube.api.obj.ChapterSegment
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
||||||
|
import com.github.libretube.extensions.navigateVideo
|
||||||
import com.github.libretube.extensions.normalize
|
import com.github.libretube.extensions.normalize
|
||||||
import com.github.libretube.extensions.parcelableList
|
import com.github.libretube.extensions.parcelableList
|
||||||
import com.github.libretube.extensions.seekBy
|
import com.github.libretube.extensions.seekBy
|
||||||
@ -143,11 +144,11 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.prev.setOnClickListener {
|
binding.prev.setOnClickListener {
|
||||||
PlayingQueue.navigatePrev()
|
playerController?.navigateVideo(PlayingQueue.getPrev() ?: return@setOnClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.next.setOnClickListener {
|
binding.next.setOnClickListener {
|
||||||
PlayingQueue.navigateNext()
|
playerController?.navigateVideo(PlayingQueue.getNext() ?: return@setOnClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf(binding.forwardTV, binding.rewindTV).forEach {
|
listOf(binding.forwardTV, binding.rewindTV).forEach {
|
||||||
@ -160,6 +161,9 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
playerController?.seekBy(PlayerHelper.seekIncrement)
|
playerController?.seekBy(PlayerHelper.seekIncrement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
childFragmentManager.setFragmentResultListener(PlayingQueueSheet.PLAYING_QUEUE_REQUEST_KEY, viewLifecycleOwner) { _, args ->
|
||||||
|
playerController?.navigateVideo(args.getString(IntentData.videoId) ?: return@setFragmentResultListener)
|
||||||
|
}
|
||||||
binding.openQueue.setOnClickListener {
|
binding.openQueue.setOnClickListener {
|
||||||
PlayingQueueSheet().show(childFragmentManager)
|
PlayingQueueSheet().show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,12 @@ import android.os.Bundle
|
|||||||
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.core.os.bundleOf
|
||||||
|
import androidx.fragment.app.setFragmentResult
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.QueueBottomSheetBinding
|
import com.github.libretube.databinding.QueueBottomSheetBinding
|
||||||
import com.github.libretube.db.DatabaseHelper
|
import com.github.libretube.db.DatabaseHelper
|
||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
@ -41,7 +44,9 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
||||||
val adapter = PlayingQueueAdapter()
|
val adapter = PlayingQueueAdapter { videoId ->
|
||||||
|
setFragmentResult(PLAYING_QUEUE_REQUEST_KEY, bundleOf(IntentData.videoId to videoId))
|
||||||
|
}
|
||||||
binding.optionsRecycler.adapter = adapter
|
binding.optionsRecycler.adapter = adapter
|
||||||
|
|
||||||
// scroll to the currently playing video in the queue
|
// scroll to the currently playing video in the queue
|
||||||
@ -201,4 +206,8 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
|||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PLAYING_QUEUE_REQUEST_KEY = "playing_queue_request_key"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ import com.github.libretube.databinding.DoubleTapOverlayBinding
|
|||||||
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
||||||
import com.github.libretube.databinding.PlayerGestureControlsViewBinding
|
import com.github.libretube.databinding.PlayerGestureControlsViewBinding
|
||||||
import com.github.libretube.extensions.dpToPx
|
import com.github.libretube.extensions.dpToPx
|
||||||
|
import com.github.libretube.extensions.navigateVideo
|
||||||
import com.github.libretube.extensions.normalize
|
import com.github.libretube.extensions.normalize
|
||||||
import com.github.libretube.extensions.round
|
import com.github.libretube.extensions.round
|
||||||
import com.github.libretube.extensions.seekBy
|
import com.github.libretube.extensions.seekBy
|
||||||
@ -257,6 +258,14 @@ abstract class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportFragmentManager.setFragmentResultListener(
|
||||||
|
PlayingQueueSheet.PLAYING_QUEUE_REQUEST_KEY,
|
||||||
|
findViewTreeLifecycleOwner()!!
|
||||||
|
) { _, args ->
|
||||||
|
(player as? MediaController)?.navigateVideo(
|
||||||
|
args.getString(IntentData.videoId) ?: return@setFragmentResultListener
|
||||||
|
)
|
||||||
|
}
|
||||||
binding.queueToggle.setOnClickListener {
|
binding.queueToggle.setOnClickListener {
|
||||||
PlayingQueueSheet().show(supportFragmentManager, null)
|
PlayingQueueSheet().show(supportFragmentManager, null)
|
||||||
}
|
}
|
||||||
@ -675,7 +684,8 @@ abstract class CustomExoPlayerView(
|
|||||||
// add a margin to the top and the bottom bar in landscape mode for notches
|
// add a margin to the top and the bottom bar in landscape mode for notches
|
||||||
val isForcedLandscape =
|
val isForcedLandscape =
|
||||||
activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
||||||
val isInLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
val isInLandscape =
|
||||||
|
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
val horizontalMargin =
|
val horizontalMargin =
|
||||||
if (isFullscreen() && (isInLandscape || isForcedLandscape)) LANDSCAPE_MARGIN_HORIZONTAL else LANDSCAPE_MARGIN_HORIZONTAL_NONE
|
if (isFullscreen() && (isInLandscape || isForcedLandscape)) LANDSCAPE_MARGIN_HORIZONTAL else LANDSCAPE_MARGIN_HORIZONTAL_NONE
|
||||||
|
|
||||||
@ -843,15 +853,16 @@ abstract class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyEvent.KEYCODE_N, KeyEvent.KEYCODE_NAVIGATE_NEXT -> {
|
KeyEvent.KEYCODE_N, KeyEvent.KEYCODE_NAVIGATE_NEXT -> {
|
||||||
PlayingQueue.navigateNext()
|
PlayingQueue.getNext()?.let { (player as? MediaController)?.navigateVideo(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -> {
|
KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -> {
|
||||||
PlayingQueue.navigatePrev()
|
PlayingQueue.getPrev()?.let { (player as? MediaController)?.navigateVideo(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyEvent.KEYCODE_F -> {
|
KeyEvent.KEYCODE_F -> {
|
||||||
val fragmentManager = ContextHelper.unwrapActivity<MainActivity>(context).supportFragmentManager
|
val fragmentManager =
|
||||||
|
ContextHelper.unwrapActivity<MainActivity>(context).supportFragmentManager
|
||||||
fragmentManager.fragments.filterIsInstance<PlayerFragment>().firstOrNull()
|
fragmentManager.fragments.filterIsInstance<PlayerFragment>().firstOrNull()
|
||||||
?.toggleFullscreen()
|
?.toggleFullscreen()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.libretube.util
|
package com.github.libretube.util
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import com.github.libretube.api.PlaylistsHelper
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
@ -20,11 +19,6 @@ object PlayingQueue {
|
|||||||
|
|
||||||
private val queueJobs = mutableListOf<Job>()
|
private val queueJobs = mutableListOf<Job>()
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener that gets called when the user selects an item from the queue
|
|
||||||
*/
|
|
||||||
private var onQueueTapListener: (StreamItem) -> Unit = {}
|
|
||||||
|
|
||||||
var repeatMode: Int = Player.REPEAT_MODE_OFF
|
var repeatMode: Int = Player.REPEAT_MODE_OFF
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
@ -223,34 +217,7 @@ object PlayingQueue {
|
|||||||
add(*streams.filter { !it.isLive }.toTypedArray(), skipExisting = true)
|
add(*streams.filter { !it.isLive }.toTypedArray(), skipExisting = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onQueueItemSelected(index: Int) {
|
|
||||||
try {
|
|
||||||
val streamItem = queue[index]
|
|
||||||
updateCurrent(streamItem)
|
|
||||||
onQueueTapListener.invoke(streamItem)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("Queue on tap", "lifecycle already ended")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun navigatePrev() {
|
|
||||||
if (!hasPrev()) return
|
|
||||||
|
|
||||||
onQueueItemSelected(currentIndex() - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun navigateNext() {
|
|
||||||
if (!hasNext()) return
|
|
||||||
|
|
||||||
onQueueItemSelected(currentIndex() + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnQueueTapListener(listener: (StreamItem) -> Unit) {
|
|
||||||
onQueueTapListener = listener
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resetToDefaults() {
|
fun resetToDefaults() {
|
||||||
repeatMode = Player.REPEAT_MODE_OFF
|
repeatMode = Player.REPEAT_MODE_OFF
|
||||||
onQueueTapListener = {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user