diff --git a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt index 71b3576e1..2c76f69dc 100644 --- a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt +++ b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt @@ -92,6 +92,7 @@ object PreferenceKeys { const val ALTERNATIVE_PIP_CONTROLS = "alternative_pip_controls" const val SKIP_SILENCE = "skip_silence" const val ENABLED_VIDEO_CODECS = "video_codecs" + const val AUTOPLAY_COUNTDOWN = "autoplay_countdown" /** * Background mode 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 ab032a2a8..d75979cdd 100644 --- a/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/PlayerHelper.kt @@ -274,6 +274,12 @@ object PlayerHelper { true ) + val autoPlayCountdown: Boolean + get() = PreferenceHelper.getBoolean( + PreferenceKeys.AUTOPLAY_COUNTDOWN, + false + ) + val seekIncrement: Long get() = PreferenceHelper.getString( PreferenceKeys.SEEK_INCREMENT, diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index b6040f926..dd3b4252c 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -923,7 +923,11 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions { binding.player.autoplayEnabled ) { transitioning = true - playNextVideo() + if (PlayerHelper.autoPlayCountdown) { + showAutoPlayCountdown() + } else { + playNextVideo() + } } if (playbackState == Player.STATE_READY) { @@ -1015,6 +1019,18 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions { } } + private fun showAutoPlayCountdown() { + binding.player.useController = false + binding.player.hideController() + binding.autoplayCountdown.setHideSelfListener { + binding.autoplayCountdown.visibility = View.GONE + binding.player.useController = true + } + binding.autoplayCountdown.startCountdown { + playNextVideo() + } + } + /** * Set up the description text with video links and timestamps */ diff --git a/app/src/main/java/com/github/libretube/ui/views/AutoplayCountdownView.kt b/app/src/main/java/com/github/libretube/ui/views/AutoplayCountdownView.kt new file mode 100644 index 000000000..2f58ca2e4 --- /dev/null +++ b/app/src/main/java/com/github/libretube/ui/views/AutoplayCountdownView.kt @@ -0,0 +1,68 @@ +package com.github.libretube.ui.views + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.FrameLayout +import androidx.core.os.postDelayed +import com.github.libretube.R +import com.github.libretube.databinding.AutoplayCountdownBinding + +class AutoplayCountdownView( + context: Context, + attributeSet: AttributeSet? +) : FrameLayout(context, attributeSet) { + private val layoutInflater = LayoutInflater.from(context) + val binding = AutoplayCountdownBinding.inflate(layoutInflater, this, true) + private var onCountdownEnd: () -> Unit = {} + private var hideSelf: () -> Unit = {} + private val handler = Handler(Looper.getMainLooper()) + private var currentTimerState = COUNTDOWN_SECONDS + + init { + binding.cancel.setOnClickListener { + handler.removeCallbacksAndMessages(TIMER_RUNNABLE_TOKEN) + hideSelf.invoke() + } + } + + fun setHideSelfListener(listener: () -> Unit) { + hideSelf = listener + } + + fun startCountdown(onEnd: () -> Unit) { + this.visibility = View.VISIBLE + onCountdownEnd = { + hideSelf.invoke() + onEnd.invoke() + } + currentTimerState = COUNTDOWN_SECONDS + binding.playNext.setOnClickListener { + handler.removeCallbacksAndMessages(TIMER_RUNNABLE_TOKEN) + onCountdownEnd.invoke() + } + updateCountdown() + } + + private fun updateCountdown() { + if (currentTimerState == 0) { + onCountdownEnd.invoke() + return + } + + binding.currentState.text = context.getString( + R.string.playing_next, + currentTimerState.toString() + ) + currentTimerState -= 1 + handler.postDelayed(1000, TIMER_RUNNABLE_TOKEN, this::updateCountdown) + } + + companion object { + private const val COUNTDOWN_SECONDS = 5 + private const val TIMER_RUNNABLE_TOKEN = "timer_runnable" + } +} diff --git a/app/src/main/res/layout/autoplay_countdown.xml b/app/src/main/res/layout/autoplay_countdown.xml new file mode 100644 index 000000000..80d1b7322 --- /dev/null +++ b/app/src/main/res/layout/autoplay_countdown.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_player.xml b/app/src/main/res/layout/fragment_player.xml index 29be2c33c..70c586f9a 100644 --- a/app/src/main/res/layout/fragment_player.xml +++ b/app/src/main/res/layout/fragment_player.xml @@ -349,6 +349,12 @@ app:drawableTint="@android:color/white" /> + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ac54ad6d6..7cb818bc6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -446,6 +446,9 @@ Category Stats for nerds Video ID + Autoplay countdown + Show a 5s countdown before auto-playing the next video. + Playing next in %1$s Download Service Shows a notification when downloading media. diff --git a/app/src/main/res/xml/player_settings.xml b/app/src/main/res/xml/player_settings.xml index 7f438e031..b64503c28 100644 --- a/app/src/main/res/xml/player_settings.xml +++ b/app/src/main/res/xml/player_settings.xml @@ -41,9 +41,9 @@ + app:title="@string/alternative_pip_controls" /> + + + app:title="@string/custom_playback_speed" />