mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 00:10: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) -> {
|
||||
videoId = args.getString(PlayerCommand.PLAY_VIDEO_BY_ID.name) ?: return
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
startPlayback()
|
||||
}
|
||||
navigateVideo(args.getString(PlayerCommand.PLAY_VIDEO_BY_ID.name) ?: return)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateVideo(videoId: String) {
|
||||
this.videoId = videoId
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
startPlayback()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSubtitleRoleFlags(subtitle: Subtitle?): Int {
|
||||
return if (subtitle?.autoGenerated != true) {
|
||||
C.ROLE_FLAG_CAPTION
|
||||
@ -180,11 +184,11 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
|
||||
|
||||
when (event) {
|
||||
PlayerEvent.Next -> {
|
||||
PlayingQueue.navigateNext()
|
||||
navigateVideo(PlayingQueue.getNext() ?: return)
|
||||
}
|
||||
|
||||
PlayerEvent.Prev -> {
|
||||
PlayingQueue.navigatePrev()
|
||||
navigateVideo(PlayingQueue.getPrev() ?: return)
|
||||
}
|
||||
|
||||
PlayerEvent.Stop -> {
|
||||
|
@ -14,7 +14,6 @@ import com.github.libretube.enums.FileType
|
||||
import com.github.libretube.extensions.serializable
|
||||
import com.github.libretube.extensions.setMetadata
|
||||
import com.github.libretube.extensions.toAndroidUri
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.activities.NoInternetActivity
|
||||
@ -67,10 +66,6 @@ open class OfflinePlayerService : AbstractPlayerService() {
|
||||
|
||||
PlayingQueue.clear()
|
||||
|
||||
PlayingQueue.setOnQueueTapListener { streamItem ->
|
||||
streamItem.url?.toID()?.let { playNextVideo(it) }
|
||||
}
|
||||
|
||||
exoPlayer?.addListener(playerListener)
|
||||
|
||||
fillQueue()
|
||||
|
@ -24,7 +24,6 @@ import com.github.libretube.db.DatabaseHelper
|
||||
import com.github.libretube.enums.PlayerCommand
|
||||
import com.github.libretube.extensions.parcelable
|
||||
import com.github.libretube.extensions.setMetadata
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.extensions.toastFromMainDispatcher
|
||||
import com.github.libretube.extensions.toastFromMainThread
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
@ -113,10 +112,6 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
||||
|
||||
if (!playerData.keepQueue) PlayingQueue.clear()
|
||||
|
||||
PlayingQueue.setOnQueueTapListener { streamItem ->
|
||||
streamItem.url?.toID()?.let { playNextVideo(it) }
|
||||
}
|
||||
|
||||
exoPlayer?.addListener(playerListener)
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@ import com.github.libretube.helpers.ThemeHelper
|
||||
import com.github.libretube.ui.viewholders.PlayingQueueViewHolder
|
||||
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 {
|
||||
val binding = QueueRowBinding.inflate(
|
||||
@ -45,14 +47,17 @@ class PlayingQueueAdapter : RecyclerView.Adapter<PlayingQueueViewHolder>() {
|
||||
)
|
||||
|
||||
root.setOnClickListener {
|
||||
val newVideoId = streamItem.url?.toID() ?: return@setOnClickListener
|
||||
|
||||
val oldPosition = PlayingQueue.currentIndex()
|
||||
// get the new position from the queue to work properly after reordering the queue
|
||||
val newPosition = PlayingQueue.getStreams().indexOfFirst {
|
||||
it.url?.toID() == streamItem.url?.toID()
|
||||
it.url?.toID() == newVideoId
|
||||
}.takeIf { it >= 0 } ?: return@setOnClickListener
|
||||
PlayingQueue.updateCurrent(streamItem)
|
||||
|
||||
// select the new item in the queue and update the selected item in the UI
|
||||
PlayingQueue.onQueueItemSelected(newPosition)
|
||||
onQueueItemSelected(newVideoId)
|
||||
notifyItemChanged(oldPosition)
|
||||
notifyItemChanged(newPosition)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
||||
import com.github.libretube.extensions.navigateVideo
|
||||
import com.github.libretube.extensions.normalize
|
||||
import com.github.libretube.extensions.parcelableList
|
||||
import com.github.libretube.extensions.seekBy
|
||||
@ -143,11 +144,11 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
}
|
||||
|
||||
binding.prev.setOnClickListener {
|
||||
PlayingQueue.navigatePrev()
|
||||
playerController?.navigateVideo(PlayingQueue.getPrev() ?: return@setOnClickListener)
|
||||
}
|
||||
|
||||
binding.next.setOnClickListener {
|
||||
PlayingQueue.navigateNext()
|
||||
playerController?.navigateVideo(PlayingQueue.getNext() ?: return@setOnClickListener)
|
||||
}
|
||||
|
||||
listOf(binding.forwardTV, binding.rewindTV).forEach {
|
||||
@ -160,6 +161,9 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
playerController?.seekBy(PlayerHelper.seekIncrement)
|
||||
}
|
||||
|
||||
childFragmentManager.setFragmentResultListener(PlayingQueueSheet.PLAYING_QUEUE_REQUEST_KEY, viewLifecycleOwner) { _, args ->
|
||||
playerController?.navigateVideo(args.getString(IntentData.videoId) ?: return@setFragmentResultListener)
|
||||
}
|
||||
binding.openQueue.setOnClickListener {
|
||||
PlayingQueueSheet().show(childFragmentManager)
|
||||
}
|
||||
|
@ -5,9 +5,12 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.media3.common.Player
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.databinding.QueueBottomSheetBinding
|
||||
import com.github.libretube.db.DatabaseHelper
|
||||
import com.github.libretube.db.DatabaseHolder
|
||||
@ -41,7 +44,9 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
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
|
||||
|
||||
// scroll to the currently playing video in the queue
|
||||
@ -201,4 +206,8 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
||||
}
|
||||
.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.PlayerGestureControlsViewBinding
|
||||
import com.github.libretube.extensions.dpToPx
|
||||
import com.github.libretube.extensions.navigateVideo
|
||||
import com.github.libretube.extensions.normalize
|
||||
import com.github.libretube.extensions.round
|
||||
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 {
|
||||
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
|
||||
val isForcedLandscape =
|
||||
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 =
|
||||
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 -> {
|
||||
PlayingQueue.navigateNext()
|
||||
PlayingQueue.getNext()?.let { (player as? MediaController)?.navigateVideo(it) }
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -> {
|
||||
PlayingQueue.navigatePrev()
|
||||
PlayingQueue.getPrev()?.let { (player as? MediaController)?.navigateVideo(it) }
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_F -> {
|
||||
val fragmentManager = ContextHelper.unwrapActivity<MainActivity>(context).supportFragmentManager
|
||||
val fragmentManager =
|
||||
ContextHelper.unwrapActivity<MainActivity>(context).supportFragmentManager
|
||||
fragmentManager.fragments.filterIsInstance<PlayerFragment>().firstOrNull()
|
||||
?.toggleFullscreen()
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.github.libretube.util
|
||||
|
||||
import android.util.Log
|
||||
import androidx.media3.common.Player
|
||||
import com.github.libretube.api.PlaylistsHelper
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
@ -20,11 +19,6 @@ object PlayingQueue {
|
||||
|
||||
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
|
||||
|
||||
fun clear() {
|
||||
@ -223,34 +217,7 @@ object PlayingQueue {
|
||||
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() {
|
||||
repeatMode = Player.REPEAT_MODE_OFF
|
||||
onQueueTapListener = {}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user