refactor advanced player options

This commit is contained in:
Bnyro 2022-08-12 14:03:55 +02:00
parent 47ed98ffc3
commit 3cde15c96f
11 changed files with 284 additions and 241 deletions

View File

@ -6,7 +6,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Rect import android.graphics.Rect
import android.net.Uri import android.net.Uri
import android.os.Build 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.DownloadDialog
import com.github.libretube.dialogs.ShareDialog import com.github.libretube.dialogs.ShareDialog
import com.github.libretube.extensions.BaseFragment 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.ChapterSegment
import com.github.libretube.obj.Segment import com.github.libretube.obj.Segment
import com.github.libretube.obj.Segments 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.ConnectionHelper
import com.github.libretube.util.CronetHelper import com.github.libretube.util.CronetHelper
import com.github.libretube.util.NowPlayingNotification import com.github.libretube.util.NowPlayingNotification
import com.github.libretube.util.OnDoubleTapEventListener
import com.github.libretube.util.PlayerHelper import com.github.libretube.util.PlayerHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.SubscriptionHelper import com.github.libretube.util.SubscriptionHelper
import com.github.libretube.util.formatShort import com.github.libretube.util.formatShort
import com.github.libretube.util.hideKeyboard import com.github.libretube.util.hideKeyboard
import com.github.libretube.util.toID import com.github.libretube.util.toID
import com.github.libretube.views.BottomSheetFragment
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.DefaultLoadControl import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayer
@ -206,8 +207,6 @@ class PlayerFragment : BaseFragment() {
setUserPrefs() setUserPrefs()
if (autoplayEnabled) playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_on)
val mainActivity = activity as MainActivity val mainActivity = activity as MainActivity
if (autoRotationEnabled) { if (autoRotationEnabled) {
// enable auto rotation // 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 // actions that don't depend on video information
private fun initializeOnClickActions() { private fun initializeOnClickActions() {
binding.closeImageView.setOnClickListener { binding.closeImageView.setOnClickListener {
@ -417,24 +537,12 @@ class PlayerFragment : BaseFragment() {
} }
// show the advanced player options // show the advanced player options
playerBinding.toggleOptions.setOnClickListener { playerBinding.toggleOptions.setOnClickListener {
if (playerBinding.advancedOptions.isVisible) { val bottomSheetFragment = BottomSheetFragment().apply {
playerBinding.toggleOptions.animate().rotation(0F).setDuration(250).start() setOnClickListeners(playerOptionsInterface)
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
} }
bottomSheetFragment.show(childFragmentManager, null)
} }
binding.playImageView.setOnClickListener { binding.playImageView.setOnClickListener {
if (!exoPlayer.isPlaying) { if (!exoPlayer.isPlaying) {
// start or go on playing // 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 // lock and unlock the player
playerBinding.lockPlayer.setOnClickListener { playerBinding.lockPlayer.setOnClickListener {
// change the locked/unlocked icon // change the locked/unlocked icon
@ -502,37 +596,7 @@ class PlayerFragment : BaseFragment() {
} }
// set default playback speed // set default playback speed
val playbackSpeeds = context?.resources?.getStringArray(R.array.playbackSpeed)!!
val playbackSpeedValues =
context?.resources?.getStringArray(R.array.playbackSpeedValues)!!
exoPlayer.setPlaybackSpeed(playbackSpeed.toFloat()) 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 // share button
binding.relPlayerShare.setOnClickListener { binding.relPlayerShare.setOnClickListener {
@ -785,7 +849,6 @@ class PlayerFragment : BaseFragment() {
// switch back to normal speed when on the end of live stream // switch back to normal speed when on the end of live stream
if (exoPlayer.duration - exoPlayer.currentPosition < 7000) { if (exoPlayer.duration - exoPlayer.currentPosition < 7000) {
exoPlayer.setPlaybackSpeed(1F) exoPlayer.setPlaybackSpeed(1F)
playerBinding.speedText.text = "1x"
playerBinding.liveSeparator.visibility = View.GONE playerBinding.liveSeparator.visibility = View.GONE
playerBinding.liveDiff.text = "" playerBinding.liveDiff.text = ""
} else { } else {
@ -911,12 +974,6 @@ class PlayerFragment : BaseFragment() {
override fun onVideoSizeChanged( override fun onVideoSizeChanged(
videoSize: VideoSize 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 // Set new width/height of view
// height or width must be cast to float as int/int will give 0 // 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.rewindTV.text = seekIncrementText
doubleTapOverlayBinding.forwardTV.text = seekIncrementText doubleTapOverlayBinding.forwardTV.text = seekIncrementText
binding.player.setOnDoubleTapListener( binding.player.setOnDoubleTapListener(
object : OnDoubleTapEventListener { object : DoubleTapInterface {
override fun onEvent(x: Float) { override fun onEvent(x: Float) {
val width = exoPlayerView.width val width = exoPlayerView.width
when { when {
@ -1234,17 +1291,17 @@ class PlayerFragment : BaseFragment() {
exoPlayer.setMediaSource(mergeSource) exoPlayer.setMediaSource(mergeSource)
} }
private fun setResolutionAndSubtitles(response: Streams) { private fun getAvailableResolutions(streams: Streams): Pair<Array<String>, Array<Uri>> {
var videosNameArray: Array<CharSequence> = arrayOf() var videosNameArray: Array<String> = arrayOf()
var videosUrlArray: Array<Uri> = arrayOf() var videosUrlArray: Array<Uri> = arrayOf()
// append hls to list if available // append hls to list if available
if (response.hls != null) { if (streams.hls != null) {
videosNameArray += getString(R.string.hls) 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) // append quality to list if it has the preferred format (e.g. MPEG)
val preferredMimeType = "video/$videoFormatPreference" val preferredMimeType = "video/$videoFormatPreference"
if (vid.url != null && vid.mimeType == preferredMimeType) { // preferred format if (vid.url != null && vid.mimeType == preferredMimeType) { // preferred format
@ -1255,6 +1312,13 @@ class PlayerFragment : BaseFragment() {
videosUrlArray += vid.url!!.toUri() 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 // create a list of subtitles
subtitle = mutableListOf() subtitle = mutableListOf()
val subtitlesNamesList = mutableListOf(context?.getString(R.string.none)!!) val subtitlesNamesList = mutableListOf(context?.getString(R.string.none)!!)
@ -1276,46 +1340,6 @@ class PlayerFragment : BaseFragment() {
.setPreferredTextLanguage(defaultSubtitleCode) .setPreferredTextLanguage(defaultSubtitleCode)
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION) .setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
trackSelector.setParameters(newParams) 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 // set media source and resolution in the beginning
@ -1324,43 +1348,11 @@ class PlayerFragment : BaseFragment() {
videosNameArray, videosNameArray,
videosUrlArray 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( private fun setStreamSource(
streams: Streams, streams: Streams,
videosNameArray: Array<CharSequence>, videosNameArray: Array<String>,
videosUrlArray: Array<Uri> videosUrlArray: Array<Uri>
) { ) {
if (defRes != "") { if (defRes != "") {
@ -1370,7 +1362,6 @@ class PlayerFragment : BaseFragment() {
val videoUri = videosUrlArray[index] val videoUri = videosUrlArray[index]
val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!) val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!)
setMediaSource(videoUri, audioUrl) setMediaSource(videoUri, audioUrl)
playerBinding.qualityText.text = videosNameArray[index]
return return
} }
} }
@ -1383,7 +1374,6 @@ class PlayerFragment : BaseFragment() {
.setSubtitleConfigurations(subtitle) .setSubtitleConfigurations(subtitle)
.build() .build()
exoPlayer.setMediaItem(mediaItem) exoPlayer.setMediaItem(mediaItem)
playerBinding.qualityText.text = context?.getString(R.string.hls)
return return
} }
@ -1392,7 +1382,6 @@ class PlayerFragment : BaseFragment() {
val videoUri = videosUrlArray[0] val videoUri = videosUrlArray[0]
val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!) val audioUrl = PlayerHelper.getAudioSource(streams.audioStreams!!)
setMediaSource(videoUri, audioUrl) setMediaSource(videoUri, audioUrl)
playerBinding.qualityText.text = videosNameArray[0]
} }
} }

View File

@ -0,0 +1,5 @@
package com.github.libretube.interfaces
interface DoubleTapInterface {
fun onEvent(x: Float)
}

View File

@ -0,0 +1,16 @@
package com.github.libretube.interfaces
interface PlayerOptionsInterface {
fun onAutoplayClicked()
fun onCaptionClicked()
fun onQualityClicked()
fun onPlaybackSpeedClicked()
fun onAspectRatioClicked()
fun onRepeatModeClicked()
}

View File

@ -1,5 +0,0 @@
package com.github.libretube.util
interface OnDoubleTapEventListener {
fun onEvent(x: Float)
}

View File

@ -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()
}
}
}

View File

@ -4,10 +4,9 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
import com.github.libretube.interfaces.DoubleTapInterface
import com.github.libretube.util.DoubleTapListener import com.github.libretube.util.DoubleTapListener
import com.github.libretube.util.OnDoubleTapEventListener
import com.google.android.exoplayer2.ui.StyledPlayerView import com.google.android.exoplayer2.ui.StyledPlayerView
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@ -18,13 +17,13 @@ internal class CustomExoPlayerView(
val TAG = "CustomExoPlayerView" val TAG = "CustomExoPlayerView"
val binding: ExoStyledPlayerControlViewBinding = ExoStyledPlayerControlViewBinding.bind(this) val binding: ExoStyledPlayerControlViewBinding = ExoStyledPlayerControlViewBinding.bind(this)
private var doubleTapListener: OnDoubleTapEventListener? = null private var doubleTapListener: DoubleTapInterface? = null
// the x-position of where the user clicked // the x-position of where the user clicked
private var xPos = 0F private var xPos = 0F
fun setOnDoubleTapListener( fun setOnDoubleTapListener(
eventListener: OnDoubleTapEventListener? eventListener: DoubleTapInterface?
) { ) {
doubleTapListener = eventListener doubleTapListener = eventListener
} }
@ -44,11 +43,6 @@ internal class CustomExoPlayerView(
} }
init { 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 // set the double click listener for rewind/forward
setOnClickListener(doubleTouchListener) setOnClickListener(doubleTouchListener)
} }

View File

@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="@android:color/white" android:tint="?attr/colorControlNormal"
android:viewportWidth="48" android:viewportWidth="48"
android:viewportHeight="48"> android:viewportHeight="48">
<path <path

View 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>

View File

@ -67,17 +67,6 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layoutDirection="ltr"> 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 <ImageButton
android:id="@+id/toggle_options" android:id="@+id/toggle_options"
style="@style/PlayerControlTop" style="@style/PlayerControlTop"
@ -89,68 +78,6 @@
</LinearLayout> </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>
<LinearLayout <LinearLayout

View File

@ -303,4 +303,6 @@
<string name="take_a_break">Time to take a break</string> <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="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="yt_shorts">Shorts</string>
<string name="no_subtitles_available">No subtitles available</string>
<string name="repeat_mode">Repeat Mode</string>
</resources> </resources>

View File

@ -157,4 +157,14 @@
</style> </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> </resources>