Merge pull request #6789 from Bnyro/master

refactor: simplify playing queue listener handling
This commit is contained in:
Bnyro 2024-11-19 13:59:58 +01:00 committed by GitHub
commit 1665b33385
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 66 additions and 60 deletions

View File

@ -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)
)
}

View File

@ -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 -> {

View File

@ -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()

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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"
}
}

View File

@ -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()
}

View File

@ -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 = {}
}
}