Merge pull request #2789 from Bnyro/master

[Audio Mode] Share, playback, queue and open video controls
This commit is contained in:
Bnyro 2023-01-21 11:54:28 +01:00 committed by GitHub
commit 33d09eb251
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 114 additions and 24 deletions

View File

@ -65,7 +65,7 @@ class BackgroundMode : Service() {
/**
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
*/
private var player: ExoPlayer? = null
var player: ExoPlayer? = null
private var playWhenReadyPlayer = true
/**

View File

@ -12,14 +12,20 @@ import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.github.libretube.R
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.databinding.FragmentAudioPlayerBinding
import com.github.libretube.enums.ShareObjectType
import com.github.libretube.extensions.toID
import com.github.libretube.obj.ShareData
import com.github.libretube.services.BackgroundMode
import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.base.BaseFragment
import com.github.libretube.ui.dialogs.ShareDialog
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
import com.github.libretube.ui.sheets.PlayingQueueSheet
import com.github.libretube.util.BackgroundHelper
import com.github.libretube.util.ImageHelper
import com.github.libretube.util.NavigationHelper
import com.github.libretube.util.PlayingQueue
@ -32,7 +38,7 @@ class AudioPlayerFragment : BaseFragment() {
private var handler = Handler(Looper.getMainLooper())
private var isPaused: Boolean = false
private lateinit var playerService: BackgroundMode
private var playerService: BackgroundMode? = null
/** Defines callbacks for service binding, passed to bindService() */
private val connection = object : ServiceConnection {
@ -86,16 +92,42 @@ class AudioPlayerFragment : BaseFragment() {
PlayingQueue.onQueueItemSelected(currentIndex + 1)
}
binding.thumbnail.setOnClickListener {
binding.openQueue.setOnClickListener {
PlayingQueueSheet().show(childFragmentManager)
}
binding.playbackOptions.setOnClickListener {
playerService?.player?.let {
PlaybackOptionsSheet(it)
.show(childFragmentManager)
}
}
binding.openVideo.setOnClickListener {
NavigationHelper.navigateVideo(
context = requireContext(),
videoId = PlayingQueue.getCurrent()?.url?.toID(),
keepQueue = true,
forceVideo = true
)
BackgroundHelper.stopBackgroundPlay(requireContext())
findNavController().popBackStack()
}
binding.share.setOnClickListener {
val currentVideo = PlayingQueue.getCurrent() ?: return@setOnClickListener
ShareDialog(
id = currentVideo.url!!.toID(),
shareObjectType = ShareObjectType.VIDEO,
shareData = ShareData(currentVideo = currentVideo.title)
).show(childFragmentManager, null)
}
// Listen for track changes due to autoplay or the notification
PlayingQueue.addOnTrackChangedListener(onTrackChangeListener)
binding.playPause.setOnClickListener {
if (!this::playerService.isInitialized) return@setOnClickListener
if (isPaused) playerService.play() else playerService.pause()
if (isPaused) playerService?.play() else playerService?.pause()
}
// load the stream info into the UI
@ -121,10 +153,8 @@ class AudioPlayerFragment : BaseFragment() {
}
private fun initializeSeekBar() {
if (!this::playerService.isInitialized) return
binding.timeBar.addOnChangeListener { _, value, fromUser ->
if (fromUser) playerService.seekToPosition(value.toLong() * 1000)
if (fromUser) playerService?.seekToPosition(value.toLong() * 1000)
}
updateSeekBar()
}
@ -133,7 +163,7 @@ class AudioPlayerFragment : BaseFragment() {
* Update the position, duration and text views belonging to the seek bar
*/
private fun updateSeekBar() {
val duration = playerService.getDuration()?.toFloat() ?: return
val duration = playerService?.getDuration()?.toFloat() ?: return
// when the video is not loaded yet, retry in 100 ms
if (duration <= 0) {
@ -142,7 +172,7 @@ class AudioPlayerFragment : BaseFragment() {
}
// get the current position from the player service
val currentPosition = playerService.getCurrentPosition()?.toFloat() ?: 0f
val currentPosition = playerService?.getCurrentPosition()?.toFloat() ?: 0f
// set the text for the indicators
binding.duration.text = DateUtils.formatElapsedTime((duration / 1000).toLong())
@ -161,7 +191,7 @@ class AudioPlayerFragment : BaseFragment() {
}
private fun handleServiceConnection() {
playerService.onIsPlayingChanged = { isPlaying ->
playerService?.onIsPlayingChanged = { isPlaying ->
binding.playPause.setIconResource(
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
)
@ -172,7 +202,7 @@ class AudioPlayerFragment : BaseFragment() {
override fun onDestroy() {
// unregister all listeners and the connected [playerService]
playerService.onIsPlayingChanged = null
playerService?.onIsPlayingChanged = null
activity?.unbindService(connection)
PlayingQueue.removeOnTrackChangedListener(onTrackChangeListener)

View File

@ -11,7 +11,7 @@ import com.github.libretube.util.PreferenceHelper
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.PlaybackParameters
class PlaybackSpeedSheet(
class PlaybackOptionsSheet(
private val player: ExoPlayer
) : ExpandedBottomSheet() {
private lateinit var binding: PlaybackBottomSheetBinding

View File

@ -30,7 +30,7 @@ import com.github.libretube.ui.interfaces.PlayerGestureOptions
import com.github.libretube.ui.interfaces.PlayerOptions
import com.github.libretube.ui.models.PlayerViewModel
import com.github.libretube.ui.sheets.BaseBottomSheet
import com.github.libretube.ui.sheets.PlaybackSpeedSheet
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
import com.github.libretube.util.AudioHelper
import com.github.libretube.util.BrightnessHelper
import com.github.libretube.util.PlayerGestureController
@ -531,7 +531,7 @@ internal class CustomExoPlayerView(
override fun onPlaybackSpeedClicked() {
player?.let {
PlaybackSpeedSheet(it as ExoPlayer).show(supportFragmentManager)
PlaybackOptionsSheet(it as ExoPlayer).show(supportFragmentManager)
}
}

View File

@ -60,11 +60,12 @@ object NavigationHelper {
playlistId: String? = null,
channelId: String? = null,
keepQueue: Boolean = false,
timeStamp: Long? = null
timeStamp: Long? = null,
forceVideo: Boolean = false
) {
if (videoId == null) return
if (PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false)) {
if (PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false) && !forceVideo) {
BackgroundHelper.stopBackgroundPlay(context)
BackgroundHelper.playOnBackground(
context,

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M21,3L3,3c-1.11,0 -2,0.89 -2,2v12c0,1.1 0.89,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.11 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12zM16,11l-7,4L9,7z" />
</vector>

View File

@ -47,8 +47,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="18sp"
android:layout_marginTop="10dp" />
android:layout_marginTop="10dp"
android:textSize="18sp" />
</LinearLayout>
@ -56,8 +56,8 @@
android:id="@+id/time_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelBehavior="gone"
android:layout_marginHorizontal="20dp" />
android:layout_marginHorizontal="20dp"
app:labelBehavior="gone" />
<FrameLayout
android:layout_width="match_parent"
@ -69,14 +69,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center"
tools:text="00:00"/>
tools:text="00:00" />
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center"
tools:text="10:15"/>
tools:text="10:15" />
</FrameLayout>
@ -84,7 +84,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginVertical="50dp">
android:layout_marginTop="24dp"
android:layout_marginBottom="36dp">
<ImageView
android:id="@+id/prev"
@ -118,4 +119,44 @@
</LinearLayout>
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardCornerRadius="18dp"
android:layout_marginBottom="30dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="15dp">
<ImageView
android:id="@+id/open_queue"
style="@style/AudioPlayerButton"
android:src="@drawable/ic_queue" />
<ImageView
android:id="@+id/playback_options"
style="@style/AudioPlayerButton"
android:layout_width="27dp"
android:layout_height="27dp"
android:src="@drawable/ic_speed" />
<ImageView
android:id="@+id/open_video"
style="@style/AudioPlayerButton"
android:src="@drawable/ic_video" />
<ImageView
android:id="@+id/share"
style="@style/AudioPlayerButton"
android:src="@drawable/ic_share" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>

View File

@ -238,4 +238,12 @@
</style>
<style name="AudioPlayerButton">
<item name="android:layout_width">30dp</item>
<item name="android:layout_height">30dp</item>
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
<item name="android:layout_marginStart">10dp</item>
<item name="android:layout_marginEnd">10dp</item>
</style>
</resources>