mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-15 14:50:30 +05:30
Merge pull request #2651 from Bnyro/master
Option for background and skip controls in PiP
This commit is contained in:
commit
70912428dd
@ -87,6 +87,7 @@ object PreferenceKeys {
|
|||||||
const val CAPTIONS_SIZE = "captions_size"
|
const val CAPTIONS_SIZE = "captions_size"
|
||||||
const val DOUBLE_TAP_TO_SEEK = "double_tap_seek"
|
const val DOUBLE_TAP_TO_SEEK = "double_tap_seek"
|
||||||
const val PAUSE_ON_QUIT = "pause_on_quit"
|
const val PAUSE_ON_QUIT = "pause_on_quit"
|
||||||
|
const val ALTERNATIVE_PIP_CONTROLS = "alternative_pip_controls"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background mode
|
* Background mode
|
||||||
|
@ -6,7 +6,8 @@ enum class PlayerEvent(val value: Int) {
|
|||||||
Forward(2),
|
Forward(2),
|
||||||
Rewind(3),
|
Rewind(3),
|
||||||
Next(5),
|
Next(5),
|
||||||
Prev(6);
|
Prev(6),
|
||||||
|
Background(7);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromInt(value: Int) = PlayerEvent.values().first { it.value == value }
|
fun fromInt(value: Int) = PlayerEvent.values().first { it.value == value }
|
||||||
|
@ -28,6 +28,7 @@ import androidx.annotation.RequiresApi
|
|||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.os.postDelayed
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@ -181,6 +182,9 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receiver for all actions in the PiP mode
|
||||||
|
*/
|
||||||
private val broadcastReceiver = object : BroadcastReceiver() {
|
private val broadcastReceiver = object : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
val action = intent?.getIntExtra(PlayerHelper.CONTROL_TYPE, 0) ?: return
|
val action = intent?.getIntExtra(PlayerHelper.CONTROL_TYPE, 0) ?: return
|
||||||
@ -197,6 +201,16 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
PlayerEvent.Rewind -> {
|
PlayerEvent.Rewind -> {
|
||||||
exoPlayer.seekTo(exoPlayer.currentPosition - PlayerHelper.seekIncrement)
|
exoPlayer.seekTo(exoPlayer.currentPosition - PlayerHelper.seekIncrement)
|
||||||
}
|
}
|
||||||
|
PlayerEvent.Next -> {
|
||||||
|
playNextVideo()
|
||||||
|
}
|
||||||
|
PlayerEvent.Background -> {
|
||||||
|
playOnBackground()
|
||||||
|
// wait some time in order for the service to get started properly
|
||||||
|
handler.postDelayed({
|
||||||
|
activity?.finish()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,13 +461,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
exoPlayer.pause()
|
exoPlayer.pause()
|
||||||
|
|
||||||
// start the background mode
|
// start the background mode
|
||||||
BackgroundHelper.playOnBackground(
|
playOnBackground()
|
||||||
requireContext(),
|
|
||||||
videoId!!,
|
|
||||||
exoPlayer.currentPosition,
|
|
||||||
playlistId,
|
|
||||||
channelId
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.relatedRecView.layoutManager = VideosAdapter.getLayout(requireContext())
|
binding.relatedRecView.layoutManager = VideosAdapter.getLayout(requireContext())
|
||||||
@ -465,6 +473,16 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun playOnBackground() {
|
||||||
|
BackgroundHelper.playOnBackground(
|
||||||
|
requireContext(),
|
||||||
|
videoId!!,
|
||||||
|
exoPlayer.currentPosition,
|
||||||
|
playlistId,
|
||||||
|
channelId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setFullscreen() {
|
private fun setFullscreen() {
|
||||||
with(binding.playerMotionLayout) {
|
with(binding.playerMotionLayout) {
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, -1)
|
getConstraintSet(R.id.start).constrainHeight(R.id.player, -1)
|
||||||
@ -1497,7 +1515,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun getPipParams(): PictureInPictureParams = PictureInPictureParams.Builder()
|
fun getPipParams(): PictureInPictureParams = PictureInPictureParams.Builder()
|
||||||
.setActions(PlayerHelper.getPIPModeActions(requireActivity(), exoPlayer.isPlaying))
|
.setActions(PlayerHelper.getPiPModeActions(requireActivity(), exoPlayer.isPlaying))
|
||||||
.apply {
|
.apply {
|
||||||
if (SDK_INT >= Build.VERSION_CODES.S) {
|
if (SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
setAutoEnterEnabled(true)
|
setAutoEnterEnabled(true)
|
||||||
|
@ -332,6 +332,12 @@ object PlayerHelper {
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val alternativePiPControls: Boolean
|
||||||
|
get() = PreferenceHelper.getBoolean(
|
||||||
|
PreferenceKeys.ALTERNATIVE_PIP_CONTROLS,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
fun getDefaultResolution(context: Context): String {
|
fun getDefaultResolution(context: Context): String {
|
||||||
return if (NetworkHelper.isNetworkMobile(context)) {
|
return if (NetworkHelper.isNetworkMobile(context)) {
|
||||||
PreferenceHelper.getString(
|
PreferenceHelper.getString(
|
||||||
@ -384,16 +390,28 @@ object PlayerHelper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create controls to use in the PiP window
|
||||||
|
*/
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun getPIPModeActions(activity: Activity, isPlaying: Boolean): ArrayList<RemoteAction> {
|
fun getPiPModeActions(activity: Activity, isPlaying: Boolean, isOfflinePlayer: Boolean = false): ArrayList<RemoteAction> {
|
||||||
val actions: ArrayList<RemoteAction> = ArrayList()
|
val actions: ArrayList<RemoteAction> = ArrayList()
|
||||||
actions.add(
|
actions.add(
|
||||||
|
if (!isOfflinePlayer && alternativePiPControls) {
|
||||||
|
getRemoteAction(
|
||||||
|
activity,
|
||||||
|
R.drawable.ic_headphones,
|
||||||
|
R.string.background_mode,
|
||||||
|
PlayerEvent.Background
|
||||||
|
)
|
||||||
|
} else {
|
||||||
getRemoteAction(
|
getRemoteAction(
|
||||||
activity,
|
activity,
|
||||||
R.drawable.ic_rewind,
|
R.drawable.ic_rewind,
|
||||||
R.string.rewind,
|
R.string.rewind,
|
||||||
PlayerEvent.Rewind
|
PlayerEvent.Rewind
|
||||||
)
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
actions.add(
|
actions.add(
|
||||||
@ -406,12 +424,21 @@ object PlayerHelper {
|
|||||||
)
|
)
|
||||||
|
|
||||||
actions.add(
|
actions.add(
|
||||||
|
if (!isOfflinePlayer && alternativePiPControls) {
|
||||||
|
getRemoteAction(
|
||||||
|
activity,
|
||||||
|
R.drawable.ic_next,
|
||||||
|
R.string.play_next,
|
||||||
|
PlayerEvent.Next
|
||||||
|
)
|
||||||
|
} else {
|
||||||
getRemoteAction(
|
getRemoteAction(
|
||||||
activity,
|
activity,
|
||||||
R.drawable.ic_forward,
|
R.drawable.ic_forward,
|
||||||
R.string.forward,
|
R.string.forward,
|
||||||
PlayerEvent.Forward
|
PlayerEvent.Forward
|
||||||
)
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
@ -428,6 +428,8 @@
|
|||||||
<string name="rewind">Rewind</string>
|
<string name="rewind">Rewind</string>
|
||||||
<string name="forward">Forward</string>
|
<string name="forward">Forward</string>
|
||||||
<string name="pause">Pause</string>
|
<string name="pause">Pause</string>
|
||||||
|
<string name="alternative_pip_controls">Alternative PiP controls</string>
|
||||||
|
<string name="alternative_pip_controls_summary">Show audio only and skip controls in PiP instead of forward and rewind</string>
|
||||||
|
|
||||||
<!-- Notification channel strings -->
|
<!-- Notification channel strings -->
|
||||||
<string name="download_channel_name">Download Service</string>
|
<string name="download_channel_name">Download Service</string>
|
||||||
|
@ -38,6 +38,13 @@
|
|||||||
app:key="picture_in_picture"
|
app:key="picture_in_picture"
|
||||||
app:title="@string/picture_in_picture" />
|
app:title="@string/picture_in_picture" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_headphones"
|
||||||
|
app:key="alternative_pip_controls"
|
||||||
|
app:title="@string/alternative_pip_controls"
|
||||||
|
android:summary="@string/alternative_pip_controls_summary"/>
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:icon="@drawable/ic_pause_filled"
|
android:icon="@drawable/ic_pause_filled"
|
||||||
|
Loading…
Reference in New Issue
Block a user