mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 16:00:31 +05:30
feat: show repeat button in audio player when playback finished
This commit is contained in:
parent
73c98368a7
commit
46acd28c26
@ -41,11 +41,11 @@ import com.github.libretube.enums.SbSkipOptions
|
|||||||
import com.github.libretube.extensions.updateParameters
|
import com.github.libretube.extensions.updateParameters
|
||||||
import com.github.libretube.obj.VideoStats
|
import com.github.libretube.obj.VideoStats
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
|
|
||||||
object PlayerHelper {
|
object PlayerHelper {
|
||||||
private const val ACTION_MEDIA_CONTROL = "media_control"
|
private const val ACTION_MEDIA_CONTROL = "media_control"
|
||||||
@ -598,7 +598,8 @@ object PlayerHelper {
|
|||||||
val chapter = chapters[index]
|
val chapter = chapters[index]
|
||||||
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
||||||
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
||||||
val isWithinMaxHighlightDuration = (currentPositionSeconds - chapter.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
val isWithinMaxHighlightDuration =
|
||||||
|
(currentPositionSeconds - chapter.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
||||||
chapter.highlightDrawable == null || isWithinMaxHighlightDuration
|
chapter.highlightDrawable == null || isWithinMaxHighlightDuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,4 +772,10 @@ object PlayerHelper {
|
|||||||
"${player.videoFormat?.width}x${player.videoFormat?.height} ${player.videoFormat?.frameRate?.toInt()}fps"
|
"${player.videoFormat?.width}x${player.videoFormat?.height} ${player.videoFormat?.frameRate?.toInt()}fps"
|
||||||
return VideoStats(videoId, videoInfo, videoQuality, audioInfo)
|
return VideoStats(videoId, videoInfo, videoQuality, audioInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPlayPauseActionIcon(player: Player) = when {
|
||||||
|
player.isPlaying -> R.drawable.ic_pause
|
||||||
|
player.playbackState == Player.STATE_ENDED -> R.drawable.ic_restart
|
||||||
|
else -> R.drawable.ic_play
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,16 +100,18 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
/**
|
/**
|
||||||
* Listener for passing playback state changes to the AudioPlayerFragment
|
* Listener for passing playback state changes to the AudioPlayerFragment
|
||||||
*/
|
*/
|
||||||
var onIsPlayingChanged: ((isPlaying: Boolean) -> Unit)? = null
|
var onStateOrPlayingChanged: ((isPlaying: Boolean) -> Unit)? = null
|
||||||
var onNewVideo: ((streams: Streams, videoId: String) -> Unit)? = null
|
var onNewVideo: ((streams: Streams, videoId: String) -> Unit)? = null
|
||||||
|
|
||||||
private val playerListener = object : Player.Listener {
|
private val playerListener = object : Player.Listener {
|
||||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||||
super.onIsPlayingChanged(isPlaying)
|
super.onIsPlayingChanged(isPlaying)
|
||||||
onIsPlayingChanged?.invoke(isPlaying)
|
onStateOrPlayingChanged?.invoke(isPlaying)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlaybackStateChanged(state: Int) {
|
override fun onPlaybackStateChanged(state: Int) {
|
||||||
|
onStateOrPlayingChanged?.invoke(player?.isPlaying ?: false)
|
||||||
|
|
||||||
when (state) {
|
when (state) {
|
||||||
Player.STATE_ENDED -> {
|
Player.STATE_ENDED -> {
|
||||||
if (PlayerHelper.shouldPlayNextVideo(playlistId != null) && !isTransitioning) playNextVideo()
|
if (PlayerHelper.shouldPlayNextVideo(playlistId != null) && !isTransitioning) playNextVideo()
|
||||||
@ -411,12 +413,4 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
fun getDuration() = player?.duration
|
fun getDuration() = player?.duration
|
||||||
|
|
||||||
fun seekToPosition(position: Long) = player?.seekTo(position)
|
fun seekToPosition(position: Long) = player?.seekTo(position)
|
||||||
|
|
||||||
fun pause() {
|
|
||||||
player?.pause()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun play() {
|
|
||||||
player?.play()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
|||||||
import com.github.libretube.extensions.normalize
|
import com.github.libretube.extensions.normalize
|
||||||
import com.github.libretube.extensions.seekBy
|
import com.github.libretube.extensions.seekBy
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.extensions.togglePlayPauseState
|
||||||
import com.github.libretube.helpers.AudioHelper
|
import com.github.libretube.helpers.AudioHelper
|
||||||
import com.github.libretube.helpers.BackgroundHelper
|
import com.github.libretube.helpers.BackgroundHelper
|
||||||
import com.github.libretube.helpers.ImageHelper
|
import com.github.libretube.helpers.ImageHelper
|
||||||
@ -188,11 +189,11 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
binding.thumbnail.setOnTouchListener(listener)
|
binding.thumbnail.setOnTouchListener(listener)
|
||||||
|
|
||||||
binding.playPause.setOnClickListener {
|
binding.playPause.setOnClickListener {
|
||||||
if (isPaused) playerService?.play() else playerService?.pause()
|
playerService?.player?.togglePlayPauseState()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.miniPlayerPause.setOnClickListener {
|
binding.miniPlayerPause.setOnClickListener {
|
||||||
if (isPaused) playerService?.play() else playerService?.pause()
|
playerService?.player?.togglePlayPauseState()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.showMore.setOnClickListener {
|
binding.showMore.setOnClickListener {
|
||||||
@ -207,7 +208,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
bar.progress = audioHelper.getVolumeWithScale(bar.max)
|
bar.progress = audioHelper.getVolumeWithScale(bar.max)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PlayerHelper.playAutomatically) updatePlayPauseButton(false)
|
if (!PlayerHelper.playAutomatically) updatePlayPauseButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun killFragment() {
|
private fun killFragment() {
|
||||||
@ -347,16 +348,18 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
handler.postDelayed(this::updateSeekBar, 200)
|
handler.postDelayed(this::updateSeekBar, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseButton(isPlaying: Boolean) {
|
private fun updatePlayPauseButton() {
|
||||||
val iconResource = if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
|
playerService?.player?.let {
|
||||||
binding.playPause.setIconResource(iconResource)
|
val iconRes = PlayerHelper.getPlayPauseActionIcon(it)
|
||||||
binding.miniPlayerPause.setImageResource(iconResource)
|
binding.playPause.setIconResource(iconRes)
|
||||||
|
binding.miniPlayerPause.setImageResource(iconRes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleServiceConnection() {
|
private fun handleServiceConnection() {
|
||||||
viewModel.player = playerService?.player
|
viewModel.player = playerService?.player
|
||||||
playerService?.onIsPlayingChanged = { isPlaying ->
|
playerService?.onStateOrPlayingChanged = { isPlaying ->
|
||||||
updatePlayPauseButton(isPlaying)
|
updatePlayPauseButton()
|
||||||
isPaused = !isPlaying
|
isPaused = !isPlaying
|
||||||
}
|
}
|
||||||
playerService?.onNewVideo = { streams, videoId ->
|
playerService?.onNewVideo = { streams, videoId ->
|
||||||
@ -373,7 +376,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
// unregister all listeners and the connected [playerService]
|
// unregister all listeners and the connected [playerService]
|
||||||
playerService?.onIsPlayingChanged = null
|
playerService?.onStateOrPlayingChanged = null
|
||||||
runCatching {
|
runCatching {
|
||||||
activity?.unbindService(connection)
|
activity?.unbindService(connection)
|
||||||
}
|
}
|
||||||
@ -384,7 +387,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSingleTap() {
|
override fun onSingleTap() {
|
||||||
if (isPaused) playerService?.play() else playerService?.pause()
|
playerService?.player?.togglePlayPauseState()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongTap() {
|
override fun onLongTap() {
|
||||||
|
@ -1160,13 +1160,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseButton() {
|
private fun updatePlayPauseButton() {
|
||||||
binding.playImageView.setImageResource(
|
binding.playImageView.setImageResource(PlayerHelper.getPlayPauseActionIcon(exoPlayer))
|
||||||
when {
|
|
||||||
exoPlayer.isPlaying -> R.drawable.ic_pause
|
|
||||||
exoPlayer.playbackState == Player.STATE_ENDED -> R.drawable.ic_restart
|
|
||||||
else -> R.drawable.ic_play
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun initializeHighlight(highlight: Segment) {
|
private suspend fun initializeHighlight(highlight: Segment) {
|
||||||
|
@ -168,7 +168,7 @@ open class CustomExoPlayerView(
|
|||||||
Player.EVENT_PLAY_WHEN_READY_CHANGED
|
Player.EVENT_PLAY_WHEN_READY_CHANGED
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
updatePlayPauseButton()
|
binding.playPauseBTN.setImageResource(PlayerHelper.getPlayPauseActionIcon(player))
|
||||||
|
|
||||||
// keep screen on if the video is playing
|
// keep screen on if the video is playing
|
||||||
keepScreenOn = player.isPlaying == true
|
keepScreenOn = player.isPlaying == true
|
||||||
@ -226,16 +226,6 @@ open class CustomExoPlayerView(
|
|||||||
|
|
||||||
open fun onPlayerEvent(player: Player, playerEvents: Player.Events) = Unit
|
open fun onPlayerEvent(player: Player, playerEvents: Player.Events) = Unit
|
||||||
|
|
||||||
private fun updatePlayPauseButton() {
|
|
||||||
binding.playPauseBTN.setImageResource(
|
|
||||||
when {
|
|
||||||
player?.isPlaying == true -> R.drawable.ic_pause
|
|
||||||
player?.playbackState == Player.STATE_ENDED -> R.drawable.ic_restart
|
|
||||||
else -> R.drawable.ic_play
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateDisplayedDurationType(showTimeLeft: Boolean? = null) {
|
private fun updateDisplayedDurationType(showTimeLeft: Boolean? = null) {
|
||||||
var shouldShowTimeLeft = showTimeLeft ?: PreferenceHelper
|
var shouldShowTimeLeft = showTimeLeft ?: PreferenceHelper
|
||||||
.getBoolean(PreferenceKeys.SHOW_TIME_LEFT, false)
|
.getBoolean(PreferenceKeys.SHOW_TIME_LEFT, false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user