diff --git a/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt b/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt
index f78b3ffd3..21a8ac25d 100644
--- a/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt
+++ b/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt
@@ -18,6 +18,7 @@ import androidx.core.net.toUri
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.PlaybackParameters
+import androidx.media3.common.Player
import androidx.media3.common.Tracks
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.cronet.CronetDataSource
@@ -53,6 +54,12 @@ object PlayerHelper {
const val ROLE_FLAG_AUTO_GEN_SUBTITLE = C.ROLE_FLAG_SUPPLEMENTARY
const val MINIMUM_BUFFER_DURATION = 1000 * 10 // exo default is 50s
+ val repeatModes = listOf(
+ Player.REPEAT_MODE_OFF to R.string.repeat_mode_none,
+ Player.REPEAT_MODE_ONE to R.string.repeat_mode_current,
+ Player.REPEAT_MODE_ALL to R.string.repeat_mode_all
+ )
+
/**
* A list of all categories that are not disabled by default
* Also update `sponsorblock_settings.xml` when modifying this!
diff --git a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
index 4f1b036d4..a10cae728 100644
--- a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
+++ b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
@@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.media3.common.Player
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -77,10 +78,15 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
}
binding.repeat.setOnClickListener {
- PlayingQueue.repeatQueue = !PlayingQueue.repeatQueue
- it.alpha = if (PlayingQueue.repeatQueue) 1f else 0.5f
+ // select the next available repeat mode
+ PlayingQueue.repeatMode = when (PlayingQueue.repeatMode) {
+ Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
+ Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
+ else -> Player.REPEAT_MODE_OFF
+ }
+ updateRepeatButton()
}
- binding.repeat.alpha = if (PlayingQueue.repeatQueue) 1f else 0.5f
+ updateRepeatButton()
binding.clearQueue.setOnClickListener {
val currentIndex = PlayingQueue.currentIndex()
@@ -135,6 +141,12 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
itemTouchHelper.attachToRecyclerView(binding.optionsRecycler)
}
+ private fun updateRepeatButton() {
+ binding.repeat.alpha = if (PlayingQueue.repeatMode == Player.REPEAT_MODE_OFF) 0.5f else 1f
+ val drawableResource = if (PlayingQueue.repeatMode == Player.REPEAT_MODE_ONE) R.drawable.ic_repeat_one else R.drawable.ic_repeat
+ binding.repeat.setImageResource(drawableResource)
+ }
+
@SuppressLint("NotifyDataSetChanged")
private fun showSortDialog() {
val sortOptions = listOf(
diff --git a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt
index f98bf9c4f..f293228a3 100644
--- a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt
+++ b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt
@@ -25,7 +25,6 @@ import androidx.core.view.updateLayoutParams
import androidx.media3.common.C
import androidx.media3.common.Player
import androidx.media3.common.text.Cue
-import androidx.media3.common.util.RepeatModeUtil
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.CaptionStyleCompat
@@ -296,10 +295,11 @@ open class CustomExoPlayerView(
context.getString(R.string.repeat_mode),
R.drawable.ic_repeat,
{
- if (player?.repeatMode == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE) {
- context.getString(R.string.repeat_mode_none)
- } else {
- context.getString(R.string.repeat_mode_current)
+ when (PlayingQueue.repeatMode) {
+ Player.REPEAT_MODE_OFF -> context.getString(R.string.repeat_mode_none)
+ Player.REPEAT_MODE_ONE -> context.getString(R.string.repeat_mode_current)
+ Player.REPEAT_MODE_ALL -> context.getString(R.string.repeat_mode_all)
+ else -> throw IllegalArgumentException()
}
}
) {
@@ -527,27 +527,10 @@ open class CustomExoPlayerView(
}
override fun onRepeatModeClicked() {
- val repeatModeNames = listOf(
- context.getString(R.string.repeat_mode_none),
- context.getString(R.string.repeat_mode_current),
- context.getString(R.string.all)
- )
// repeat mode options dialog
BaseBottomSheet()
- .setSimpleItems(repeatModeNames) { index ->
- PlayingQueue.repeatQueue = when (index) {
- 0 -> {
- player?.repeatMode = Player.REPEAT_MODE_OFF
- false
- }
-
- 1 -> {
- player?.repeatMode = Player.REPEAT_MODE_ONE
- false
- }
-
- else -> true
- }
+ .setSimpleItems(PlayerHelper.repeatModes.map { context.getString(it.second) }) { index ->
+ PlayingQueue.repeatMode = PlayerHelper.repeatModes[index].first
}
.show(supportFragmentManager)
}
diff --git a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt
index 61ba7db80..f2b5897db 100644
--- a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt
+++ b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt
@@ -1,6 +1,7 @@
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
import com.github.libretube.api.obj.StreamItem
@@ -20,7 +21,7 @@ object PlayingQueue {
*/
private var onQueueTapListener: (StreamItem) -> Unit = {}
- var repeatQueue: Boolean = false
+ var repeatMode: Int = Player.REPEAT_MODE_OFF
fun clear() = queue.clear()
@@ -51,12 +52,30 @@ object PlayingQueue {
}
// return the next item, or if repeating enabled, the first one of the queue
- fun getNext(): String? = queue.getOrNull(currentIndex() + 1)?.url?.toID()
- ?: queue.firstOrNull()?.url?.toID()?.takeIf { repeatQueue }
+ fun getNext(): String? {
+ if (repeatMode != Player.REPEAT_MODE_ONE) {
+ queue.getOrNull(currentIndex() + 1)?.url?.toID()?.let { return it }
+ }
+
+ return when (repeatMode) {
+ Player.REPEAT_MODE_ALL -> queue.firstOrNull()?.url?.toID()
+ Player.REPEAT_MODE_ONE -> currentStream?.url?.toID()
+ else -> null
+ }
+ }
// return the previous item, or if repeating enabled, the last one of the queue
- fun getPrev(): String? = queue.getOrNull(currentIndex() - 1)?.url?.toID()
- ?: queue.lastOrNull()?.url?.toID()?.takeIf { repeatQueue }
+ fun getPrev(): String? {
+ if (repeatMode != Player.REPEAT_MODE_ONE) {
+ queue.getOrNull(currentIndex() - 1)?.url?.toID()?.let { return it }
+ }
+
+ return when (repeatMode) {
+ Player.REPEAT_MODE_ALL -> queue.lastOrNull()?.url?.toID()
+ Player.REPEAT_MODE_ONE -> currentStream?.url?.toID()
+ else -> null
+ }
+ }
fun hasPrev() = getPrev() != null
@@ -214,7 +233,7 @@ object PlayingQueue {
}
fun resetToDefaults() {
- repeatQueue = false
+ repeatMode = Player.REPEAT_MODE_OFF
onQueueTapListener = {}
}
diff --git a/app/src/main/res/drawable/ic_repeat_one.xml b/app/src/main/res/drawable/ic_repeat_one.xml
new file mode 100644
index 000000000..e8c7449eb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_repeat_one.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8e8a90bc2..4426cb2d3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -270,6 +270,7 @@
Zoom
None
Current
+ Repeat all
Backup & restore
Backup
Picture-in-Picture