mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 06:10:31 +05:30
refactor advanced player options
This commit is contained in:
parent
47ed98ffc3
commit
3cde15c96f
@ -6,7 +6,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
@ -45,6 +44,8 @@ import com.github.libretube.dialogs.AddToPlaylistDialog
|
||||
import com.github.libretube.dialogs.DownloadDialog
|
||||
import com.github.libretube.dialogs.ShareDialog
|
||||
import com.github.libretube.extensions.BaseFragment
|
||||
import com.github.libretube.interfaces.DoubleTapInterface
|
||||
import com.github.libretube.interfaces.PlayerOptionsInterface
|
||||
import com.github.libretube.obj.ChapterSegment
|
||||
import com.github.libretube.obj.Segment
|
||||
import com.github.libretube.obj.Segments
|
||||
@ -57,13 +58,13 @@ import com.github.libretube.util.BackgroundHelper
|
||||
import com.github.libretube.util.ConnectionHelper
|
||||
import com.github.libretube.util.CronetHelper
|
||||
import com.github.libretube.util.NowPlayingNotification
|
||||
import com.github.libretube.util.OnDoubleTapEventListener
|
||||
import com.github.libretube.util.PlayerHelper
|
||||
import com.github.libretube.util.RetrofitInstance
|
||||
import com.github.libretube.util.SubscriptionHelper
|
||||
import com.github.libretube.util.formatShort
|
||||
import com.github.libretube.util.hideKeyboard
|
||||
import com.github.libretube.util.toID
|
||||
import com.github.libretube.views.BottomSheetFragment
|
||||
import com.google.android.exoplayer2.C
|
||||
import com.google.android.exoplayer2.DefaultLoadControl
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
@ -206,8 +207,6 @@ class PlayerFragment : BaseFragment() {
|
||||
|
||||
setUserPrefs()
|
||||
|
||||
if (autoplayEnabled) playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_on)
|
||||
|
||||
val mainActivity = activity as MainActivity
|
||||
if (autoRotationEnabled) {
|
||||
// enable auto rotation
|
||||
@ -397,6 +396,127 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private val playerOptionsInterface = object : PlayerOptionsInterface {
|
||||
override fun onAutoplayClicked() {
|
||||
// toggle autoplay
|
||||
autoplayEnabled = !autoplayEnabled
|
||||
}
|
||||
|
||||
override fun onCaptionClicked() {
|
||||
if (streams.subtitles == null || streams.subtitles!!.isEmpty()) {
|
||||
Toast.makeText(context, R.string.no_subtitles_available, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
val subtitlesNamesList = mutableListOf(context?.getString(R.string.none)!!)
|
||||
val subtitleCodesList = mutableListOf("")
|
||||
streams.subtitles!!.forEach {
|
||||
subtitlesNamesList += it.name!!
|
||||
subtitleCodesList += it.code!!
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.captions)
|
||||
.setItems(subtitlesNamesList.toTypedArray()) { _, index ->
|
||||
val newParams = if (index != 0) {
|
||||
// caption selected
|
||||
|
||||
// get the caption name and language
|
||||
val captionLanguage = subtitlesNamesList[index]
|
||||
val captionLanguageCode = subtitleCodesList[index]
|
||||
|
||||
// select the new caption preference
|
||||
trackSelector.buildUponParameters()
|
||||
.setPreferredTextLanguages(
|
||||
captionLanguage,
|
||||
captionLanguageCode
|
||||
)
|
||||
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
|
||||
} else {
|
||||
// none selected
|
||||
// disable captions
|
||||
trackSelector.buildUponParameters()
|
||||
.setPreferredTextLanguage("")
|
||||
}
|
||||
|
||||
// set the new caption language
|
||||
trackSelector.setParameters(newParams)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onQualityClicked() {
|
||||
// get the available resolutions
|
||||
val (videosNameArray, videosUrlArray) = getAvailableResolutions(streams)
|
||||
|
||||
// Dialog for quality selection
|
||||
val lastPosition = exoPlayer.currentPosition
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.choose_quality_dialog)
|
||||
.setItems(
|
||||
videosNameArray
|
||||
) { _, which ->
|
||||
if (
|
||||
videosNameArray[which] == getString(R.string.hls) ||
|
||||
videosNameArray[which] == "LBRY HLS"
|
||||
) {
|
||||
// no need to merge sources if using hls
|
||||
val mediaItem: MediaItem = MediaItem.Builder()
|
||||
.setUri(videosUrlArray[which])
|
||||
.setSubtitleConfigurations(subtitle)
|
||||
.build()
|
||||
exoPlayer.setMediaItem(mediaItem)
|
||||
} else {
|
||||
val videoUri = videosUrlArray[which]
|
||||
val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!)
|
||||
setMediaSource(videoUri, audioUrl)
|
||||
}
|
||||
exoPlayer.seekTo(lastPosition)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onPlaybackSpeedClicked() {
|
||||
val playbackSpeeds = context?.resources?.getStringArray(R.array.playbackSpeed)!!
|
||||
val playbackSpeedValues =
|
||||
context?.resources?.getStringArray(R.array.playbackSpeedValues)!!
|
||||
|
||||
// change playback speed dialog
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.change_playback_speed)
|
||||
.setItems(playbackSpeeds) { _, index ->
|
||||
// set the new playback speed
|
||||
val newPlaybackSpeed = playbackSpeedValues[index].toFloat()
|
||||
exoPlayer.setPlaybackSpeed(newPlaybackSpeed)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onAspectRatioClicked() {
|
||||
// switching between original aspect ratio (black bars) and zoomed to fill device screen
|
||||
val aspectRatioModes = arrayOf(
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT,
|
||||
AspectRatioFrameLayout.RESIZE_MODE_ZOOM,
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FILL
|
||||
)
|
||||
val index = aspectRatioModes.indexOf(exoPlayerView.resizeMode)
|
||||
val newAspectRatioMode =
|
||||
if (index + 1 < aspectRatioModes.size) aspectRatioModes[index + 1]
|
||||
else aspectRatioModes[0]
|
||||
exoPlayerView.resizeMode = newAspectRatioMode
|
||||
}
|
||||
|
||||
override fun onRepeatModeClicked() {
|
||||
// repeat toggle button
|
||||
if (exoPlayer.repeatMode == RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL) {
|
||||
// turn off repeat mode
|
||||
exoPlayer.repeatMode = RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
|
||||
} else {
|
||||
exoPlayer.repeatMode = RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actions that don't depend on video information
|
||||
private fun initializeOnClickActions() {
|
||||
binding.closeImageView.setOnClickListener {
|
||||
@ -417,24 +537,12 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
// show the advanced player options
|
||||
playerBinding.toggleOptions.setOnClickListener {
|
||||
if (playerBinding.advancedOptions.isVisible) {
|
||||
playerBinding.toggleOptions.animate().rotation(0F).setDuration(250).start()
|
||||
playerBinding.advancedOptions.visibility = View.GONE
|
||||
} else {
|
||||
playerBinding.toggleOptions.animate().rotation(180F).setDuration(250).start()
|
||||
playerBinding.advancedOptions.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
// autoplay toggle button
|
||||
playerBinding.autoplayLL.setOnClickListener {
|
||||
autoplayEnabled = if (autoplayEnabled) {
|
||||
playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_off)
|
||||
false
|
||||
} else {
|
||||
playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_on)
|
||||
true
|
||||
val bottomSheetFragment = BottomSheetFragment().apply {
|
||||
setOnClickListeners(playerOptionsInterface)
|
||||
}
|
||||
bottomSheetFragment.show(childFragmentManager, null)
|
||||
}
|
||||
|
||||
binding.playImageView.setOnClickListener {
|
||||
if (!exoPlayer.isPlaying) {
|
||||
// start or go on playing
|
||||
@ -471,20 +579,6 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// switching between original aspect ratio (black bars) and zoomed to fill device screen
|
||||
val aspectRatioModes = arrayOf(
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT,
|
||||
AspectRatioFrameLayout.RESIZE_MODE_ZOOM,
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FILL
|
||||
)
|
||||
playerBinding.aspectRatioButton.setOnClickListener {
|
||||
val index = aspectRatioModes.indexOf(exoPlayerView.resizeMode)
|
||||
val newAspectRatioMode =
|
||||
if (index + 1 < aspectRatioModes.size) aspectRatioModes[index + 1]
|
||||
else aspectRatioModes[0]
|
||||
exoPlayerView.resizeMode = newAspectRatioMode
|
||||
}
|
||||
|
||||
// lock and unlock the player
|
||||
playerBinding.lockPlayer.setOnClickListener {
|
||||
// change the locked/unlocked icon
|
||||
@ -502,37 +596,7 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
// set default playback speed
|
||||
val playbackSpeeds = context?.resources?.getStringArray(R.array.playbackSpeed)!!
|
||||
val playbackSpeedValues =
|
||||
context?.resources?.getStringArray(R.array.playbackSpeedValues)!!
|
||||
exoPlayer.setPlaybackSpeed(playbackSpeed.toFloat())
|
||||
val speedIndex = playbackSpeedValues.indexOf(playbackSpeed)
|
||||
playerBinding.speedText.text = playbackSpeeds[speedIndex]
|
||||
|
||||
// change playback speed button
|
||||
playerBinding.speedText.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.change_playback_speed)
|
||||
.setItems(playbackSpeeds) { _, index ->
|
||||
// set the new playback speed
|
||||
val newPlaybackSpeed = playbackSpeedValues[index].toFloat()
|
||||
exoPlayer.setPlaybackSpeed(newPlaybackSpeed)
|
||||
playerBinding.speedText.text = playbackSpeeds[index]
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
// repeat toggle button
|
||||
playerBinding.repeatToggle.setOnClickListener {
|
||||
if (exoPlayer.repeatMode == RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL) {
|
||||
// turn off repeat mode
|
||||
exoPlayer.repeatMode = RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
|
||||
playerBinding.repeatToggle.setColorFilter(Color.GRAY)
|
||||
} else {
|
||||
exoPlayer.repeatMode = RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL
|
||||
playerBinding.repeatToggle.setColorFilter(Color.WHITE)
|
||||
}
|
||||
}
|
||||
|
||||
// share button
|
||||
binding.relPlayerShare.setOnClickListener {
|
||||
@ -785,7 +849,6 @@ class PlayerFragment : BaseFragment() {
|
||||
// switch back to normal speed when on the end of live stream
|
||||
if (exoPlayer.duration - exoPlayer.currentPosition < 7000) {
|
||||
exoPlayer.setPlaybackSpeed(1F)
|
||||
playerBinding.speedText.text = "1x"
|
||||
playerBinding.liveSeparator.visibility = View.GONE
|
||||
playerBinding.liveDiff.text = ""
|
||||
} else {
|
||||
@ -911,12 +974,6 @@ class PlayerFragment : BaseFragment() {
|
||||
override fun onVideoSizeChanged(
|
||||
videoSize: VideoSize
|
||||
) {
|
||||
// show the resolution in the video resolution text view
|
||||
if (playerBinding.qualityText.text == context?.getString(R.string.hls)) {
|
||||
playerBinding.qualityText.text =
|
||||
"${context?.getString(R.string.hls)} (${videoSize.height}p)"
|
||||
}
|
||||
|
||||
// Set new width/height of view
|
||||
// height or width must be cast to float as int/int will give 0
|
||||
|
||||
@ -1075,7 +1132,7 @@ class PlayerFragment : BaseFragment() {
|
||||
doubleTapOverlayBinding.rewindTV.text = seekIncrementText
|
||||
doubleTapOverlayBinding.forwardTV.text = seekIncrementText
|
||||
binding.player.setOnDoubleTapListener(
|
||||
object : OnDoubleTapEventListener {
|
||||
object : DoubleTapInterface {
|
||||
override fun onEvent(x: Float) {
|
||||
val width = exoPlayerView.width
|
||||
when {
|
||||
@ -1234,17 +1291,17 @@ class PlayerFragment : BaseFragment() {
|
||||
exoPlayer.setMediaSource(mergeSource)
|
||||
}
|
||||
|
||||
private fun setResolutionAndSubtitles(response: Streams) {
|
||||
var videosNameArray: Array<CharSequence> = arrayOf()
|
||||
private fun getAvailableResolutions(streams: Streams): Pair<Array<String>, Array<Uri>> {
|
||||
var videosNameArray: Array<String> = arrayOf()
|
||||
var videosUrlArray: Array<Uri> = arrayOf()
|
||||
|
||||
// append hls to list if available
|
||||
if (response.hls != null) {
|
||||
if (streams.hls != null) {
|
||||
videosNameArray += getString(R.string.hls)
|
||||
videosUrlArray += response.hls.toUri()
|
||||
videosUrlArray += streams.hls.toUri()
|
||||
}
|
||||
|
||||
for (vid in response.videoStreams!!) {
|
||||
for (vid in streams.videoStreams!!) {
|
||||
// append quality to list if it has the preferred format (e.g. MPEG)
|
||||
val preferredMimeType = "video/$videoFormatPreference"
|
||||
if (vid.url != null && vid.mimeType == preferredMimeType) { // preferred format
|
||||
@ -1255,6 +1312,13 @@ class PlayerFragment : BaseFragment() {
|
||||
videosUrlArray += vid.url!!.toUri()
|
||||
}
|
||||
}
|
||||
return Pair(videosNameArray, videosUrlArray)
|
||||
}
|
||||
|
||||
private fun setResolutionAndSubtitles(response: Streams) {
|
||||
// get the available resolutions
|
||||
val (videosNameArray, videosUrlArray) = getAvailableResolutions(response)
|
||||
|
||||
// create a list of subtitles
|
||||
subtitle = mutableListOf()
|
||||
val subtitlesNamesList = mutableListOf(context?.getString(R.string.none)!!)
|
||||
@ -1276,46 +1340,6 @@ class PlayerFragment : BaseFragment() {
|
||||
.setPreferredTextLanguage(defaultSubtitleCode)
|
||||
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
|
||||
trackSelector.setParameters(newParams)
|
||||
playerBinding.captions.setImageResource(R.drawable.ic_caption)
|
||||
}
|
||||
|
||||
// captions selection dialog
|
||||
// hide caption selection view if no subtitles available
|
||||
if (response.subtitles.isEmpty()) playerBinding.captions.visibility = View.GONE
|
||||
playerBinding.captions.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.captions)
|
||||
.setItems(subtitlesNamesList.toTypedArray()) { _, index ->
|
||||
val newParams = if (index != 0) {
|
||||
// caption selected
|
||||
|
||||
// get the caption name and language
|
||||
val captionLanguage = subtitlesNamesList[index]
|
||||
val captionLanguageCode = subtitleCodesList[index]
|
||||
|
||||
// update the icon of the captions button
|
||||
playerBinding.captions.setImageResource(R.drawable.ic_caption)
|
||||
|
||||
// select the new caption preference
|
||||
trackSelector.buildUponParameters()
|
||||
.setPreferredTextLanguages(
|
||||
captionLanguage,
|
||||
captionLanguageCode
|
||||
)
|
||||
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
|
||||
} else {
|
||||
// none selected
|
||||
playerBinding.captions.setImageResource(R.drawable.ic_caption_outlined)
|
||||
|
||||
// disable captions
|
||||
trackSelector.buildUponParameters()
|
||||
.setPreferredTextLanguage("")
|
||||
}
|
||||
|
||||
// set the new caption language
|
||||
trackSelector.setParameters(newParams)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
// set media source and resolution in the beginning
|
||||
@ -1324,43 +1348,11 @@ class PlayerFragment : BaseFragment() {
|
||||
videosNameArray,
|
||||
videosUrlArray
|
||||
)
|
||||
|
||||
playerBinding.qualityText.setOnClickListener {
|
||||
// Dialog for quality selection
|
||||
val builder: MaterialAlertDialogBuilder? = activity?.let {
|
||||
MaterialAlertDialogBuilder(it)
|
||||
}
|
||||
val lastPosition = exoPlayer.currentPosition
|
||||
builder!!.setTitle(R.string.choose_quality_dialog)
|
||||
.setItems(
|
||||
videosNameArray
|
||||
) { _, which ->
|
||||
if (
|
||||
videosNameArray[which] == getString(R.string.hls) ||
|
||||
videosNameArray[which] == "LBRY HLS"
|
||||
) {
|
||||
// no need to merge sources if using hls
|
||||
val mediaItem: MediaItem = MediaItem.Builder()
|
||||
.setUri(videosUrlArray[which])
|
||||
.setSubtitleConfigurations(subtitle)
|
||||
.build()
|
||||
exoPlayer.setMediaItem(mediaItem)
|
||||
} else {
|
||||
val videoUri = videosUrlArray[which]
|
||||
val audioUrl = PlayerHelper.getAudioSource(response.audioStreams!!)
|
||||
setMediaSource(videoUri, audioUrl)
|
||||
}
|
||||
exoPlayer.seekTo(lastPosition)
|
||||
playerBinding.qualityText.text = videosNameArray[which]
|
||||
}
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setStreamSource(
|
||||
streams: Streams,
|
||||
videosNameArray: Array<CharSequence>,
|
||||
videosNameArray: Array<String>,
|
||||
videosUrlArray: Array<Uri>
|
||||
) {
|
||||
if (defRes != "") {
|
||||
@ -1370,7 +1362,6 @@ class PlayerFragment : BaseFragment() {
|
||||
val videoUri = videosUrlArray[index]
|
||||
val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!)
|
||||
setMediaSource(videoUri, audioUrl)
|
||||
playerBinding.qualityText.text = videosNameArray[index]
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1383,7 +1374,6 @@ class PlayerFragment : BaseFragment() {
|
||||
.setSubtitleConfigurations(subtitle)
|
||||
.build()
|
||||
exoPlayer.setMediaItem(mediaItem)
|
||||
playerBinding.qualityText.text = context?.getString(R.string.hls)
|
||||
return
|
||||
}
|
||||
|
||||
@ -1392,7 +1382,6 @@ class PlayerFragment : BaseFragment() {
|
||||
val videoUri = videosUrlArray[0]
|
||||
val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!)
|
||||
setMediaSource(videoUri, audioUrl)
|
||||
playerBinding.qualityText.text = videosNameArray[0]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.github.libretube.interfaces
|
||||
|
||||
interface DoubleTapInterface {
|
||||
fun onEvent(x: Float)
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.github.libretube.interfaces
|
||||
|
||||
interface PlayerOptionsInterface {
|
||||
|
||||
fun onAutoplayClicked()
|
||||
|
||||
fun onCaptionClicked()
|
||||
|
||||
fun onQualityClicked()
|
||||
|
||||
fun onPlaybackSpeedClicked()
|
||||
|
||||
fun onAspectRatioClicked()
|
||||
|
||||
fun onRepeatModeClicked()
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.github.libretube.util
|
||||
|
||||
interface OnDoubleTapEventListener {
|
||||
fun onEvent(x: Float)
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.github.libretube.views
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.github.libretube.databinding.BottomSheetBinding
|
||||
import com.github.libretube.interfaces.PlayerOptionsInterface
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
|
||||
class BottomSheetFragment : BottomSheetDialogFragment() {
|
||||
private lateinit var binding: BottomSheetBinding
|
||||
private lateinit var playerOptionsInterface: PlayerOptionsInterface
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = BottomSheetBinding.inflate(layoutInflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
fun setOnClickListeners(playerOptionsInterface: PlayerOptionsInterface) {
|
||||
this.playerOptionsInterface = playerOptionsInterface
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.aspectRatio.setOnClickListener {
|
||||
playerOptionsInterface.onAspectRatioClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
binding.quality.setOnClickListener {
|
||||
playerOptionsInterface.onQualityClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
binding.playbackSpeed.setOnClickListener {
|
||||
playerOptionsInterface.onPlaybackSpeedClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
binding.captions.setOnClickListener {
|
||||
playerOptionsInterface.onCaptionClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
binding.autoplay.setOnClickListener {
|
||||
playerOptionsInterface.onAutoplayClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
binding.repeatMode.setOnClickListener {
|
||||
playerOptionsInterface.onRepeatModeClicked()
|
||||
this.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
@ -4,10 +4,9 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
||||
import com.github.libretube.interfaces.DoubleTapInterface
|
||||
import com.github.libretube.util.DoubleTapListener
|
||||
import com.github.libretube.util.OnDoubleTapEventListener
|
||||
import com.google.android.exoplayer2.ui.StyledPlayerView
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@ -18,13 +17,13 @@ internal class CustomExoPlayerView(
|
||||
val TAG = "CustomExoPlayerView"
|
||||
val binding: ExoStyledPlayerControlViewBinding = ExoStyledPlayerControlViewBinding.bind(this)
|
||||
|
||||
private var doubleTapListener: OnDoubleTapEventListener? = null
|
||||
private var doubleTapListener: DoubleTapInterface? = null
|
||||
|
||||
// the x-position of where the user clicked
|
||||
private var xPos = 0F
|
||||
|
||||
fun setOnDoubleTapListener(
|
||||
eventListener: OnDoubleTapEventListener?
|
||||
eventListener: DoubleTapInterface?
|
||||
) {
|
||||
doubleTapListener = eventListener
|
||||
}
|
||||
@ -44,11 +43,6 @@ internal class CustomExoPlayerView(
|
||||
}
|
||||
|
||||
init {
|
||||
setControllerVisibilityListener {
|
||||
// hide the advanced options
|
||||
binding.toggleOptions.animate().rotation(0F).setDuration(250).start()
|
||||
binding.advancedOptions.visibility = View.GONE
|
||||
}
|
||||
// set the double click listener for rewind/forward
|
||||
setOnClickListener(doubleTouchListener)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="@android:color/white"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
|
44
app/src/main/res/layout/bottom_sheet.xml
Normal file
44
app/src/main/res/layout/bottom_sheet.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/quality"
|
||||
style="@style/BottomSheetItem"
|
||||
android:drawableStart="@drawable/ic_hd"
|
||||
android:text="@string/quality" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/playbackSpeed"
|
||||
style="@style/BottomSheetItem"
|
||||
android:layout_marginTop="8dp"
|
||||
android:drawableStart="@drawable/ic_speed"
|
||||
android:text="@string/playback_speed" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/captions"
|
||||
style="@style/BottomSheetItem"
|
||||
android:drawableStart="@drawable/ic_caption"
|
||||
android:text="@string/captions" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/autoplay"
|
||||
style="@style/BottomSheetItem"
|
||||
android:drawableStart="@drawable/ic_play"
|
||||
android:text="@string/player_autoplay" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/repeatMode"
|
||||
style="@style/BottomSheetItem"
|
||||
android:drawableStart="@drawable/ic_repeat"
|
||||
android:text="@string/repeat_mode" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/aspectRatio"
|
||||
style="@style/BottomSheetItem"
|
||||
android:drawableStart="@drawable/ic_aspect_ratio"
|
||||
android:text="@string/aspect_ratio" />
|
||||
</LinearLayout>
|
@ -67,17 +67,6 @@
|
||||
android:layout_gravity="center"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/speed_text"
|
||||
style="@style/PlayerControlTop"
|
||||
android:text="1x"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/quality_text"
|
||||
style="@style/PlayerControlTop"
|
||||
android:text="@string/hls" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/toggle_options"
|
||||
style="@style/PlayerControlTop"
|
||||
@ -89,68 +78,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/advanced_options"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginHorizontal="3dp"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/autoplayLL"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="1.5dp"
|
||||
android:text="@string/player_autoplay"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/autoplayIV"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:src="@drawable/ic_toggle_off" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/captions"
|
||||
style="@style/PlayerControlTop"
|
||||
android:src="@drawable/ic_caption_outlined"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/repeat_toggle"
|
||||
style="@style/PlayerControlTop"
|
||||
android:src="@drawable/ic_repeat"
|
||||
app:tint="@android:color/darker_gray" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/aspect_ratio_button"
|
||||
style="@style/PlayerControlTop"
|
||||
android:src="@drawable/ic_aspect_ratio" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -303,4 +303,6 @@
|
||||
<string name="take_a_break">Time to take a break</string>
|
||||
<string name="already_spent_time">You already spent %1$s minutes in the app, time to take a break.</string>
|
||||
<string name="yt_shorts">Shorts</string>
|
||||
<string name="no_subtitles_available">No subtitles available</string>
|
||||
<string name="repeat_mode">Repeat Mode</string>
|
||||
</resources>
|
||||
|
@ -157,4 +157,14 @@
|
||||
|
||||
</style>
|
||||
|
||||
<style name="BottomSheetItem">
|
||||
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:drawablePadding">20dp</item>
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:padding">10dp</item>
|
||||
|
||||
</style>
|
||||
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user