Merge pull request #4128 from Bnyro/master

Show time left when clicking player duration
This commit is contained in:
Bnyro 2023-06-27 11:57:21 +02:00 committed by GitHub
commit b771d89067
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 41 deletions

View File

@ -100,6 +100,7 @@ object PreferenceKeys {
const val FULLSCREEN_GESTURES = "fullscreen_gestures"
const val UNLIMITED_SEARCH_HISTORY = "unlimited_search_history"
const val SB_HIGHLIGHTS = "sb_highlights"
const val SHOW_TIME_LEFT = "show_time_left"
/**
* Background mode

View File

@ -799,25 +799,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
}
}
@SuppressLint("SetTextI18n")
private fun refreshLiveStatus() {
// switch back to normal speed when on the end of live stream
if (exoPlayer.duration - exoPlayer.currentPosition < 7000) {
exoPlayer.setPlaybackSpeed(1F)
playerBinding.timeSeparator.visibility = View.GONE
playerBinding.liveDiff.text = ""
} else {
// live stream but not watching at the end/live position
playerBinding.timeSeparator.visibility = View.VISIBLE
val diffText = DateUtils.formatElapsedTime(
(exoPlayer.duration - exoPlayer.currentPosition) / 1000
)
playerBinding.liveDiff.text = "-$diffText"
}
// call the function again after 100ms
handler.postDelayed(this@PlayerFragment::refreshLiveStatus, 100)
}
/**
* Seek to saved watch position if available */
private fun seekToWatchPosition() {
@ -882,16 +863,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
}
}
private fun handleLiveVideo() {
playerBinding.exoPosition.visibility = View.GONE
playerBinding.liveDiff.visibility = View.VISIBLE
playerBinding.duration.text = getString(R.string.live)
playerBinding.exoTime.setOnClickListener {
exoPlayer.seekTo(exoPlayer.duration)
}
refreshLiveStatus()
}
@SuppressLint("SetTextI18n")
private fun initializePlayerView() {
// initialize the player view actions
@ -916,11 +887,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
R.string.subscribers,
streams.uploaderSubscriberCount.formatShort()
)
player.isLive = streams.livestream
}
// duration that's not greater than 0 indicates that the video is live
if (streams.livestream) handleLiveVideo()
playerBinding.exoTitle.text = streams.title
// init the chapters recyclerview
@ -962,6 +931,13 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
override fun onPlaybackStateChanged(playbackState: Int) {
saveWatchPosition()
// set the playback speed to one if having reached the end of a livestream
if (playbackState == Player.STATE_BUFFERING && binding.player.isLive &&
exoPlayer.duration - exoPlayer.currentPosition < 700
) {
exoPlayer.setPlaybackSpeed(1f)
}
// check if video has ended, next video is available and autoplay is enabled.
if (
playbackState == Player.STATE_ENDED &&

View File

@ -7,6 +7,7 @@ import android.content.res.Configuration
import android.graphics.Color
import android.os.Handler
import android.os.Looper
import android.text.format.DateUtils
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
@ -17,9 +18,11 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.os.postDelayed
import androidx.core.view.ViewCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.marginStart
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
@ -30,6 +33,7 @@ import androidx.media3.ui.PlayerView
import androidx.media3.ui.SubtitleView
import androidx.media3.ui.TimeBar
import com.github.libretube.R
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.databinding.DoubleTapOverlayBinding
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
import com.github.libretube.databinding.PlayerGestureControlsViewBinding
@ -39,6 +43,7 @@ import com.github.libretube.extensions.round
import com.github.libretube.helpers.AudioHelper
import com.github.libretube.helpers.BrightnessHelper
import com.github.libretube.helpers.PlayerHelper
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.obj.BottomSheetItem
import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.interfaces.PlayerGestureOptions
@ -72,6 +77,13 @@ open class CustomExoPlayerView(
private val runnableHandler = Handler(Looper.getMainLooper())
var isPlayerLocked: Boolean = false
var isLive: Boolean = false
set(value) {
field = value
updateDisplayedDurationType()
updateCurrentPosition()
}
/**
* Preferences
@ -177,6 +189,21 @@ open class CustomExoPlayerView(
enqueueHideControllerTask()
}
})
// restore the duration type from the previous session
updateDisplayedDurationType()
binding.duration.setOnClickListener {
updateDisplayedDurationType(true)
}
binding.timeLeft.setOnClickListener {
updateDisplayedDurationType(false)
}
binding.position.setOnClickListener {
if (isLive) player?.let { it.seekTo(it.duration) }
}
updateCurrentPosition()
}
open fun onPlayerEvent(player: Player, playerEvents: Player.Events) = Unit
@ -191,6 +218,19 @@ open class CustomExoPlayerView(
)
}
private fun updateDisplayedDurationType(showTimeLeft: Boolean? = null) {
var shouldShowTimeLeft = showTimeLeft ?: PreferenceHelper
.getBoolean(PreferenceKeys.SHOW_TIME_LEFT, false)
// always show the time left only if it's a livestream
if (isLive) shouldShowTimeLeft = true
if (showTimeLeft != null) {
// save whether to show time left or duration for next session
PreferenceHelper.putBoolean(PreferenceKeys.SHOW_TIME_LEFT, shouldShowTimeLeft)
}
binding.timeLeft.isVisible = shouldShowTimeLeft
binding.duration.isGone = shouldShowTimeLeft
}
private fun enqueueHideControllerTask() {
handler.postDelayed(AUTO_HIDE_CONTROLLER_DELAY, HIDE_CONTROLLER_TOKEN) {
hideController()
@ -568,6 +608,19 @@ open class CustomExoPlayerView(
}
}
@SuppressLint("SetTextI18n")
private fun updateCurrentPosition() {
val position = player?.currentPosition?.div(1000) ?: 0
val duration = player?.duration?.takeIf { it != C.TIME_UNSET }?.div(1000) ?: 0
val timeLeft = duration - position
binding.position.text =
if (isLive) context.getString(R.string.live) else DateUtils.formatElapsedTime(position)
binding.timeLeft.text = "-${DateUtils.formatElapsedTime(timeLeft)}"
runnableHandler.postDelayed(100, UPDATE_POSITION_TOKEN, this::updateCurrentPosition)
}
open fun getTopBarMarginDp(): Int {
return if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) 10 else 0
}
@ -676,6 +729,7 @@ open class CustomExoPlayerView(
private const val HIDE_CONTROLLER_TOKEN = "hideController"
private const val HIDE_FORWARD_BUTTON_TOKEN = "hideForwardButton"
private const val HIDE_REWIND_BUTTON_TOKEN = "hideRewindButton"
private const val UPDATE_POSITION_TOKEN = "updatePosition"
private const val SUBTITLE_BOTTOM_PADDING_FRACTION = 0.158f
private const val ANIMATION_DURATION = 100L

View File

@ -251,19 +251,12 @@
android:layout_marginStart="10dp">
<TextView
android:id="@id/exo_position"
android:id="@+id/position"
style="@style/TimeString"
android:text="00:00"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/liveDiff"
style="@style/TimeString"
android:visibility="gone"
tools:text="05:10" />
<TextView
android:id="@+id/time_separator"
style="@style/TimeString"
android:text=" • "
tools:ignore="HardcodedText" />
@ -274,6 +267,13 @@
android:text="00:00"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/timeLeft"
style="@style/TimeString"
android:text="00:00"
android:visibility="gone"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout