Skip to content

Commit cc7aba6

Browse files
authored
Merge pull request libre-tube#7323 from Bnyro/master
feat: smoothen background player -> new video player and video player -> new background player transitions
2 parents 805d1f2 + 0cd2456 commit cc7aba6

4 files changed

Lines changed: 97 additions & 67 deletions

File tree

app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
package com.github.libretube.helpers
22

3+
import android.annotation.SuppressLint
34
import android.app.NotificationManager
45
import android.content.Context
56
import android.content.Intent
6-
import android.os.Handler
7-
import android.os.Looper
87
import android.os.Process
9-
import androidx.annotation.OptIn
108
import androidx.core.content.getSystemService
119
import androidx.core.os.bundleOf
12-
import androidx.core.os.postDelayed
1310
import androidx.fragment.app.commitNow
1411
import androidx.fragment.app.replace
15-
import androidx.media3.common.util.UnstableApi
1612
import com.github.libretube.NavDirections
1713
import com.github.libretube.R
1814
import com.github.libretube.constants.IntentData
@@ -29,8 +25,6 @@ import com.github.libretube.ui.views.SingleViewTouchableMotionLayout
2925
import com.github.libretube.util.PlayingQueue
3026

3127
object NavigationHelper {
32-
private val handler = Handler(Looper.getMainLooper())
33-
3428
fun navigateChannel(context: Context, channelUrlOrId: String?) {
3529
if (channelUrlOrId == null) return
3630

@@ -52,6 +46,7 @@ object NavigationHelper {
5246
* Navigate to the given video using the other provided parameters as well
5347
* If the audio only mode is enabled, play it in the background, else as a normal video
5448
*/
49+
@SuppressLint("UnsafeOptInUsageError")
5550
fun navigateVideo(
5651
context: Context,
5752
videoUrlOrId: String?,
@@ -60,22 +55,27 @@ object NavigationHelper {
6055
keepQueue: Boolean = false,
6156
timestamp: Long = 0,
6257
alreadyStarted: Boolean = false,
63-
forceVideo: Boolean = false
58+
forceVideo: Boolean = false,
59+
audioOnlyPlayerRequested: Boolean = false,
6460
) {
6561
if (videoUrlOrId == null) return
6662

67-
if (PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false) && !forceVideo) {
68-
navigateAudio(context, videoUrlOrId.toID(), playlistId, channelId, keepQueue, timestamp)
69-
return
70-
}
71-
63+
// attempt to attach to the current media session first by using the corresponding
64+
// video/audio player instance
7265
val activity = ContextHelper.unwrapActivity<MainActivity>(context)
7366
val attachedToRunningPlayer = activity.runOnPlayerFragment {
7467
try {
7568
this.playNextVideo(videoUrlOrId.toID())
76-
// maximize player
77-
this.binding.playerMotionLayout.transitionToStart()
7869
PlayingQueue.clear()
70+
71+
if (audioOnlyPlayerRequested) {
72+
// switch to audio only player
73+
this.switchToAudioMode()
74+
} else {
75+
// maximize player
76+
this.binding.playerMotionLayout.transitionToStart()
77+
}
78+
7979
true
8080
} catch (e: Exception) {
8181
this.onDestroy()
@@ -84,45 +84,46 @@ object NavigationHelper {
8484
}
8585
if (attachedToRunningPlayer) return
8686

87-
val playerData =
88-
PlayerData(videoUrlOrId.toID(), playlistId, channelId, keepQueue, timestamp)
89-
val bundle = bundleOf(
90-
IntentData.playerData to playerData,
91-
IntentData.alreadyStarted to alreadyStarted
92-
)
93-
activity.supportFragmentManager.commitNow {
94-
replace<PlayerFragment>(R.id.container, args = bundle)
95-
}
96-
}
87+
val attachedToRunningAudioPlayer = activity.runOnAudioPlayerFragment {
88+
this.playNextVideo(videoUrlOrId.toID())
89+
PlayingQueue.clear()
90+
91+
if (!audioOnlyPlayerRequested) {
92+
// switch to video only player
93+
this.switchToVideoMode()
94+
} else {
95+
// maximize player
96+
this.binding.playerMotionLayout.transitionToStart()
97+
}
9798

98-
@OptIn(UnstableApi::class)
99-
fun navigateAudio(
100-
context: Context,
101-
videoId: String,
102-
playlistId: String? = null,
103-
channelId: String? = null,
104-
keepQueue: Boolean = false,
105-
timestamp: Long = 0,
106-
minimizeByDefault: Boolean = false
107-
) {
108-
val activity = ContextHelper.unwrapActivity<MainActivity>(context)
109-
val attachedToRunningPlayer = activity.runOnAudioPlayerFragment {
110-
this.playNextVideo(videoId)
11199
true
112100
}
113-
if (attachedToRunningPlayer) return
114-
115-
BackgroundHelper.playOnBackground(
116-
context,
117-
videoId,
118-
timestamp,
119-
playlistId,
120-
channelId,
121-
keepQueue
122-
)
101+
if (attachedToRunningAudioPlayer) return
102+
103+
val audioOnlyMode = PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false)
104+
if (audioOnlyPlayerRequested || (audioOnlyMode && !forceVideo)) {
105+
// in contrast to the video player, the audio player doesn't start a media service on
106+
// its own!
107+
BackgroundHelper.playOnBackground(
108+
context,
109+
videoUrlOrId.toID(),
110+
timestamp,
111+
playlistId,
112+
channelId,
113+
keepQueue
114+
)
123115

124-
handler.postDelayed(500) {
125-
openAudioPlayerFragment(context, minimizeByDefault = minimizeByDefault)
116+
openAudioPlayerFragment(context, minimizeByDefault = true)
117+
} else {
118+
openVideoPlayerFragment(
119+
context,
120+
videoUrlOrId.toID(),
121+
playlistId,
122+
channelId,
123+
keepQueue,
124+
timestamp,
125+
alreadyStarted
126+
)
126127
}
127128
}
128129

@@ -153,6 +154,31 @@ object NavigationHelper {
153154
}
154155
}
155156

157+
/**
158+
* Starts the video player fragment for an already existing med
159+
*/
160+
fun openVideoPlayerFragment(
161+
context: Context,
162+
videoId: String,
163+
playlistId: String? = null,
164+
channelId: String? = null,
165+
keepQueue: Boolean = false,
166+
timestamp: Long = 0,
167+
alreadyStarted: Boolean = false
168+
) {
169+
val activity = ContextHelper.unwrapActivity<BaseActivity>(context)
170+
171+
val playerData =
172+
PlayerData(videoId, playlistId, channelId, keepQueue, timestamp)
173+
val bundle = bundleOf(
174+
IntentData.playerData to playerData,
175+
IntentData.alreadyStarted to alreadyStarted
176+
)
177+
activity.supportFragmentManager.commitNow {
178+
replace<PlayerFragment>(R.id.container, args = bundle)
179+
}
180+
}
181+
156182
/**
157183
* Open a large, zoomable image preview
158184
*/

app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.github.libretube.enums.PlayerCommand
3333
import com.github.libretube.extensions.navigateVideo
3434
import com.github.libretube.extensions.normalize
3535
import com.github.libretube.extensions.seekBy
36+
import com.github.libretube.extensions.toID
3637
import com.github.libretube.extensions.togglePlayPauseState
3738
import com.github.libretube.extensions.updateIfChanged
3839
import com.github.libretube.helpers.AudioHelper
@@ -174,19 +175,7 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
174175
}
175176

176177
binding.openVideo.setOnClickListener {
177-
playerController?.sendCustomCommand(
178-
AbstractPlayerService.runPlayerActionCommand,
179-
bundleOf(PlayerCommand.TOGGLE_AUDIO_ONLY_MODE.name to false)
180-
)
181-
182-
killFragment(false)
183-
184-
NavigationHelper.navigateVideo(
185-
context = requireContext(),
186-
videoUrlOrId = PlayingQueue.getCurrent()?.url,
187-
alreadyStarted = true,
188-
forceVideo = true
189-
)
178+
switchToVideoMode()
190179
}
191180

192181
childFragmentManager.setFragmentResultListener(
@@ -271,6 +260,21 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
271260
}
272261
}
273262

263+
fun switchToVideoMode() {
264+
playerController?.sendCustomCommand(
265+
AbstractPlayerService.runPlayerActionCommand,
266+
bundleOf(PlayerCommand.TOGGLE_AUDIO_ONLY_MODE.name to false)
267+
)
268+
269+
killFragment(false)
270+
271+
NavigationHelper.openVideoPlayerFragment(
272+
context = requireContext(),
273+
videoId = PlayingQueue.getCurrent()?.url!!.toID(),
274+
alreadyStarted = true,
275+
)
276+
}
277+
274278
private fun killFragment(stopPlayer: Boolean) {
275279
viewModel.isMiniPlayerVisible.value = false
276280

app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions {
218218
}
219219

220220
PlayerEvent.Background -> {
221-
playOnBackground()
221+
switchToAudioMode()
222222
// wait some time in order for the service to get started properly
223223
handler.postDelayed(500) {
224224
pipActivity?.moveTaskToBack(false)
@@ -698,7 +698,7 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions {
698698

699699
binding.relPlayerBackground.setOnClickListener {
700700
// start the background mode
701-
playOnBackground()
701+
switchToAudioMode()
702702
}
703703

704704
binding.relPlayerPip.isVisible =
@@ -777,7 +777,7 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions {
777777
chaptersViewModel.maxSheetHeightPx = maxHeight
778778
}
779779

780-
private fun playOnBackground() {
780+
fun switchToAudioMode() {
781781
playerController.sendCustomCommand(
782782
AbstractPlayerService.runPlayerActionCommand,
783783
bundleOf(PlayerCommand.TOGGLE_AUDIO_ONLY_MODE.name to true)

app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
5757
when (optionsList[which]) {
5858
// Start the background mode
5959
R.string.playOnBackground -> {
60-
NavigationHelper.navigateAudio(requireContext(), videoId, minimizeByDefault = true)
60+
NavigationHelper.navigateVideo(requireContext(), videoId, audioOnlyPlayerRequested = true)
6161
}
6262
// Add Video to Playlist Dialog
6363
R.string.addToPlaylist -> {

0 commit comments

Comments
 (0)