Merge pull request #998 from Bnyro/master

previous and next buttons for the player
This commit is contained in:
Bnyro 2022-08-08 17:25:39 +02:00 committed by GitHub
commit 45b10393e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 100 additions and 19 deletions

View File

@ -164,6 +164,7 @@ class PlayerFragment : BaseFragment() {
private var defaultSubtitleCode = "" private var defaultSubtitleCode = ""
private var sponsorBlockEnabled = true private var sponsorBlockEnabled = true
private var sponsorBlockNotifications = true private var sponsorBlockNotifications = true
private var skipButtonsEnabled = false
/** /**
* for autoplay * for autoplay
@ -176,6 +177,11 @@ class PlayerFragment : BaseFragment() {
*/ */
private lateinit var nowPlayingNotification: NowPlayingNotification private lateinit var nowPlayingNotification: NowPlayingNotification
/**
* history of played videos in the current lifecycle
*/
val videoIds = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
arguments?.let { arguments?.let {
@ -204,7 +210,7 @@ class PlayerFragment : BaseFragment() {
setUserPrefs() setUserPrefs()
if (autoplayEnabled == true) playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_on) if (autoplayEnabled) playerBinding.autoplayIV.setImageResource(R.drawable.ic_toggle_on)
val mainActivity = activity as MainActivity val mainActivity = activity as MainActivity
if (autoRotationEnabled) { if (autoRotationEnabled) {
@ -314,6 +320,11 @@ class PlayerFragment : BaseFragment() {
if (defaultSubtitleCode.contains("-")) { if (defaultSubtitleCode.contains("-")) {
defaultSubtitleCode = defaultSubtitleCode.split("-")[0] defaultSubtitleCode = defaultSubtitleCode.split("-")[0]
} }
skipButtonsEnabled = PreferenceHelper.getBoolean(
PreferenceKeys.SKIP_BUTTONS,
false
)
} }
private fun initializeTransitionLayout() { private fun initializeTransitionLayout() {
@ -566,8 +577,6 @@ class PlayerFragment : BaseFragment() {
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen_exit) playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen_exit)
playerBinding.exoTitle.visibility = View.VISIBLE playerBinding.exoTitle.visibility = View.VISIBLE
scaleControls(1.3F)
val mainActivity = activity as MainActivity val mainActivity = activity as MainActivity
if (!autoRotationEnabled) { if (!autoRotationEnabled) {
// different orientations of the video are only available when auto rotation is disabled // different orientations of the video are only available when auto rotation is disabled
@ -602,8 +611,6 @@ class PlayerFragment : BaseFragment() {
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen) playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen)
playerBinding.exoTitle.visibility = View.INVISIBLE playerBinding.exoTitle.visibility = View.INVISIBLE
scaleControls(1F)
if (!autoRotationEnabled) { if (!autoRotationEnabled) {
// switch back to portrait mode if auto rotation disabled // switch back to portrait mode if auto rotation disabled
val mainActivity = activity as MainActivity val mainActivity = activity as MainActivity
@ -613,11 +620,6 @@ class PlayerFragment : BaseFragment() {
Globals.IS_FULL_SCREEN = false Globals.IS_FULL_SCREEN = false
} }
private fun scaleControls(scaleFactor: Float) {
playerBinding.exoPlayPause.scaleX = scaleFactor
playerBinding.exoPlayPause.scaleY = scaleFactor
}
private fun toggleDescription() { private fun toggleDescription() {
if (binding.descLinLayout.isVisible) { if (binding.descLinLayout.isVisible) {
// hide the description and chapters // hide the description and chapters
@ -746,6 +748,7 @@ class PlayerFragment : BaseFragment() {
} }
} }
} }
videoIds += videoId!!
} }
run() run()
} }
@ -754,7 +757,18 @@ class PlayerFragment : BaseFragment() {
* set the videoId of the next stream for autoplay * set the videoId of the next stream for autoplay
*/ */
private fun setNextStream() { private fun setNextStream() {
nextStreamId = streams.relatedStreams!![0].url.toID() // don't play a video if it got played before already
var index = 0
while (nextStreamId == null || nextStreamId == videoId!! ||
(
videoIds.contains(nextStreamId) &&
videoIds.indexOf(videoId) > videoIds.indexOf(nextStreamId)
)
) {
nextStreamId = streams.relatedStreams!![index].url.toID()
if (index + 1 < streams.relatedStreams!!.size) index += 1
else break
}
if (playlistId == null) return if (playlistId == null) return
if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId!!) if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId!!)
// search for the next videoId in the playlist // search for the next videoId in the playlist
@ -823,18 +837,17 @@ class PlayerFragment : BaseFragment() {
// used for autoplay and skipping to next video // used for autoplay and skipping to next video
private fun playNextVideo() { private fun playNextVideo() {
if (nextStreamId == null) return
// check whether there is a new video in the queue // check whether there is a new video in the queue
// by making sure that the next and the current video aren't the same // by making sure that the next and the current video aren't the same
saveWatchPosition() saveWatchPosition()
// forces the comments to reload for the new video // forces the comments to reload for the new video
commentsLoaded = false commentsLoaded = false
binding.commentsRecView.adapter = null binding.commentsRecView.adapter = null
if (videoId != nextStreamId) {
// save the id of the next stream as videoId and load the next video // save the id of the next stream as videoId and load the next video
videoId = nextStreamId videoId = nextStreamId
playVideo() playVideo()
} }
}
private fun prepareExoPlayerView() { private fun prepareExoPlayerView() {
exoPlayerView.apply { exoPlayerView.apply {
@ -882,7 +895,7 @@ class PlayerFragment : BaseFragment() {
} }
// duration that's not greater than 0 indicates that the video is live // duration that's not greater than 0 indicates that the video is live
if (!(response.duration!! > 0)) { if (response.duration!! <= 0) {
isLive = true isLive = true
handleLiveVideo() handleLiveVideo()
} }
@ -1052,6 +1065,22 @@ class PlayerFragment : BaseFragment() {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
} }
} }
// next and previous buttons
playerBinding.skipPrev.visibility = if (
skipButtonsEnabled && videoIds.indexOf(videoId!!) != 0
) View.VISIBLE else View.INVISIBLE
playerBinding.skipNext.visibility = if (skipButtonsEnabled) View.VISIBLE else View.INVISIBLE
playerBinding.skipPrev.setOnClickListener {
val index = videoIds.indexOf(videoId!!) - 1
videoId = videoIds[index]
playVideo()
}
playerBinding.skipNext.setOnClickListener {
playNextVideo()
}
} }
private fun enableDoubleTapToSeek() { private fun enableDoubleTapToSeek() {

View File

@ -58,6 +58,7 @@ object PreferenceKeys {
const val PLAYER_AUDIO_FORMAT = "player_audio_format" const val PLAYER_AUDIO_FORMAT = "player_audio_format"
const val PLAYER_AUDIO_QUALITY = "player_audio_quality" const val PLAYER_AUDIO_QUALITY = "player_audio_quality"
const val DEFAULT_SUBTITLE = "default_subtitle" const val DEFAULT_SUBTITLE = "default_subtitle"
const val SKIP_BUTTONS = "skip_buttons"
/** /**
* Download * Download

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="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" />
</vector>

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="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" />
</vector>

View File

@ -19,7 +19,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="30dp"
android:visibility="invisible"> android:visibility="invisible">
<ImageView <ImageView
@ -61,7 +60,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginEnd="30dp"
android:visibility="invisible"> android:visibility="invisible">
<ImageView <ImageView

View File

@ -291,12 +291,28 @@
android:gravity="center" android:gravity="center"
android:padding="20dp"> android:padding="20dp">
<ImageView
android:id="@+id/skip_prev"
style="@style/PlayerControlCenter"
android:background="?android:selectableItemBackgroundBorderless"
android:src="@drawable/ic_prev"
android:visibility="invisible"
app:tint="@android:color/white" />
<ImageButton <ImageButton
android:id="@id/exo_play_pause" android:id="@id/exo_play_pause"
style="@style/ExoStyledControls.Button.Center.PlayPause" style="@style/ExoStyledControls.Button.Center.PlayPause"
android:background="?android:selectableItemBackgroundBorderless" android:background="?android:selectableItemBackgroundBorderless"
app:tint="@android:color/white" /> app:tint="@android:color/white" />
<ImageView
android:id="@+id/skip_next"
style="@style/PlayerControlCenter"
android:background="?android:selectableItemBackgroundBorderless"
android:src="@drawable/ic_next"
android:visibility="invisible"
app:tint="@android:color/white" />
</LinearLayout> </LinearLayout>
</merge> </merge>

View File

@ -292,4 +292,6 @@
<string name="downloadsucceeded">Download succeeded</string> <string name="downloadsucceeded">Download succeeded</string>
<string name="share_with_time">Share with start time</string> <string name="share_with_time">Share with start time</string>
<string name="export_subscriptions">Export Subscriptions</string> <string name="export_subscriptions">Export Subscriptions</string>
<string name="skip_buttons">Skip buttons</string>
<string name="skip_buttons_summary">Show buttons to skip to the next or previous video.</string>
</resources> </resources>

View File

@ -107,6 +107,14 @@
</style> </style>
<style name="PlayerControlCenter">
<item name="android:layout_width">42dp</item>
<item name="android:layout_height">42dp</item>
<item name="android:backgroundTint">@android:color/white</item>
<item name="android:layout_marginStart">10dp</item>
<item name="android:layout_marginEnd">10dp</item>
</style>
<style name="PlayerControlTop"> <style name="PlayerControlTop">
<item name="android:padding">9dp</item> <item name="android:padding">9dp</item>

View File

@ -77,6 +77,13 @@
app:key="default_subtitle" app:key="default_subtitle"
app:title="@string/default_subtitle_language" /> app:title="@string/default_subtitle_language" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_next"
android:summary="@string/skip_buttons_summary"
app:key="skip_buttons"
app:title="@string/skip_buttons" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/behavior"> <PreferenceCategory app:title="@string/behavior">