Skip to content

Commit 35f52e8

Browse files
committed
refactor(offline player): make compatible with no internet activity
1 parent e2cbc0e commit 35f52e8

8 files changed

Lines changed: 127 additions & 102 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
android:name=".ui.activities.NoInternetActivity"
4646
android:label="@string/noInternet"
4747
android:launchMode="singleTop"
48+
android:supportsPictureInPicture="true"
4849
android:screenOrientation="locked" />
4950

5051
<activity
@@ -113,13 +114,6 @@
113114

114115
</activity>
115116

116-
<activity
117-
android:name=".ui.activities.OfflinePlayerActivity"
118-
android:configChanges="keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout|orientation|uiMode"
119-
android:launchMode="singleTop"
120-
android:label="@string/player"
121-
android:supportsPictureInPicture="true" />
122-
123117
<activity
124118
android:name=".ui.activities.MainActivity"
125119
android:configChanges="keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout|orientation|uiMode"

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,30 @@ import com.github.libretube.constants.PreferenceKeys
1616
import com.github.libretube.enums.PlaylistType
1717
import com.github.libretube.extensions.toID
1818
import com.github.libretube.parcelable.PlayerData
19+
import com.github.libretube.ui.activities.AbstractPlayerHostActivity
1920
import com.github.libretube.ui.activities.MainActivity
2021
import com.github.libretube.ui.activities.ZoomableImageActivity
2122
import com.github.libretube.ui.base.BaseActivity
2223
import com.github.libretube.ui.fragments.AudioPlayerFragment
2324
import com.github.libretube.ui.fragments.DownloadSortingOrder
2425
import com.github.libretube.ui.fragments.DownloadTab
2526
import com.github.libretube.ui.fragments.PlayerFragment
26-
import com.github.libretube.ui.views.SingleViewTouchableMotionLayout
2727
import com.github.libretube.util.PlayingQueue
2828

2929
object NavigationHelper {
3030
fun navigateChannel(context: Context, channelUrlOrId: String?) {
3131
if (channelUrlOrId == null) return
3232

33-
val activity = ContextHelper.unwrapActivity<MainActivity>(context)
33+
// navigating to channels is only supported in the main activity, not in the no internet activity
34+
val activity = ContextHelper.tryUnwrapActivity<MainActivity>(context) ?: return
3435
activity.navController.navigate(NavDirections.openChannel(channelUrlOrId.toID()))
3536
try {
3637
// minimize player if currently expanded
37-
if (activity.binding.mainMotionLayout.progress == 0f) {
38-
activity.binding.mainMotionLayout.transitionToEnd()
39-
activity.findViewById<SingleViewTouchableMotionLayout>(R.id.playerMotionLayout)
40-
.transitionToEnd()
38+
activity.runOnPlayerFragment {
39+
binding.playerMotionLayout.transitionToEnd()
40+
true
4141
}
42+
activity.minimizePlayerContainerLayout()
4243
} catch (e: Exception) {
4344
e.printStackTrace()
4445
}
@@ -70,7 +71,7 @@ object NavigationHelper {
7071

7172
// attempt to attach to the current media session first by using the corresponding
7273
// video/audio player instance
73-
val activity = ContextHelper.unwrapActivity<MainActivity>(context)
74+
val activity = ContextHelper.unwrapActivity<AbstractPlayerHostActivity>(context)
7475
val attachedToRunningPlayer = activity.runOnPlayerFragment {
7576
try {
7677
PlayingQueue.clearAfterCurrent()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.github.libretube.ui.activities
2+
3+
import com.github.libretube.ui.base.BaseActivity
4+
import com.github.libretube.ui.fragments.AudioPlayerFragment
5+
import com.github.libretube.ui.fragments.PlayerFragment
6+
7+
abstract class AbstractPlayerHostActivity: BaseActivity() {
8+
abstract fun minimizePlayerContainerLayout()
9+
abstract fun maximizePlayerContainerLayout()
10+
abstract fun setPlayerContainerProgress(progress: Float)
11+
12+
abstract fun clearSearchViewFocus(): Boolean
13+
14+
15+
/**
16+
* Attempt to run code on the player fragment if running
17+
* Returns true if a running player fragment was found and the action got consumed, else false
18+
*/
19+
fun runOnPlayerFragment(action: PlayerFragment.() -> Boolean): Boolean {
20+
return supportFragmentManager.fragments.filterIsInstance<PlayerFragment>()
21+
.firstOrNull()
22+
?.let(action)
23+
?: false
24+
}
25+
26+
fun runOnAudioPlayerFragment(action: AudioPlayerFragment.() -> Boolean): Boolean {
27+
return supportFragmentManager.fragments.filterIsInstance<AudioPlayerFragment>()
28+
.firstOrNull()
29+
?.let(action)
30+
?: false
31+
}
32+
}

app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ import kotlinx.coroutines.Dispatchers
6363
import kotlinx.coroutines.launch
6464
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
6565

66-
class MainActivity : BaseActivity() {
67-
lateinit var binding: ActivityMainBinding
66+
class MainActivity : AbstractPlayerHostActivity() {
67+
private lateinit var binding: ActivityMainBinding
6868
lateinit var navController: NavController
6969

7070
private lateinit var searchView: SearchView
@@ -423,16 +423,6 @@ class MainActivity : BaseActivity() {
423423
return super.onCreateOptionsMenu(menu)
424424
}
425425

426-
/**
427-
* @return whether the search view focus was cleared successfully
428-
*/
429-
fun clearSearchViewFocus(): Boolean {
430-
if (!this::searchView.isInitialized || !searchView.anyChildFocused()) return false
431-
432-
searchView.clearFocus()
433-
return true
434-
}
435-
436426
/**
437427
* Update the query text in the search bar without opening the search suggestions
438428
*/
@@ -646,24 +636,6 @@ class MainActivity : BaseActivity() {
646636
return super.onKeyUp(keyCode, event)
647637
}
648638

649-
/**
650-
* Attempt to run code on the player fragment if running
651-
* Returns true if a running player fragment was found and the action got consumed, else false
652-
*/
653-
fun runOnPlayerFragment(action: PlayerFragment.() -> Boolean): Boolean {
654-
return supportFragmentManager.fragments.filterIsInstance<PlayerFragment>()
655-
.firstOrNull()
656-
?.let(action)
657-
?: false
658-
}
659-
660-
fun runOnAudioPlayerFragment(action: AudioPlayerFragment.() -> Boolean): Boolean {
661-
return supportFragmentManager.fragments.filterIsInstance<AudioPlayerFragment>()
662-
.firstOrNull()
663-
?.let(action)
664-
?: false
665-
}
666-
667639
fun startPlaylistExport(
668640
playlistId: String,
669641
playlistName: String,
@@ -704,4 +676,28 @@ class MainActivity : BaseActivity() {
704676
}
705677
.show()
706678
}
679+
680+
override fun minimizePlayerContainerLayout() {
681+
binding.mainMotionLayout.transitionToEnd()
682+
}
683+
684+
override fun maximizePlayerContainerLayout() {
685+
binding.mainMotionLayout.transitionToStart()
686+
}
687+
688+
override fun setPlayerContainerProgress(progress: Float) {
689+
if (!NavBarHelper.hasTabs()) return
690+
691+
binding.mainMotionLayout.progress = progress
692+
}
693+
694+
/**
695+
* @return whether the search view focus was cleared successfully
696+
*/
697+
override fun clearSearchViewFocus(): Boolean {
698+
if (!this::searchView.isInitialized || !searchView.anyChildFocused()) return false
699+
700+
searchView.clearFocus()
701+
return true
702+
}
707703
}

app/src/main/java/com/github/libretube/ui/activities/NoInternetActivity.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,26 @@ import android.os.Bundle
55
import com.github.libretube.constants.IntentData
66
import com.github.libretube.databinding.ActivityNointernetBinding
77
import com.github.libretube.helpers.NavigationHelper
8-
import com.github.libretube.ui.base.BaseActivity
8+
import com.github.libretube.ui.extensions.onSystemInsets
9+
10+
class NoInternetActivity : AbstractPlayerHostActivity() {
11+
private lateinit var binding: ActivityNointernetBinding
912

10-
class NoInternetActivity : BaseActivity() {
1113
override fun onCreate(savedInstanceState: Bundle?) {
1214
super.onCreate(savedInstanceState)
1315

14-
val binding = ActivityNointernetBinding.inflate(layoutInflater)
16+
binding = ActivityNointernetBinding.inflate(layoutInflater)
1517
setContentView(binding.root)
18+
19+
// add padding to fragment containers to prevent overlap with edge-to-edge status bars
20+
binding.root.onSystemInsets { _, systemBarInsets ->
21+
with (binding.fragment) {
22+
setPadding(paddingLeft, systemBarInsets.top, paddingRight, systemBarInsets.bottom)
23+
}
24+
with (binding.container) {
25+
setPadding(paddingLeft, paddingTop, paddingRight, systemBarInsets.bottom)
26+
}
27+
}
1628
}
1729

1830
override fun onNewIntent(intent: Intent) {
@@ -22,4 +34,13 @@ class NoInternetActivity : BaseActivity() {
2234
NavigationHelper.openAudioPlayerFragment(this, offlinePlayer = true)
2335
}
2436
}
37+
38+
// all these actions are no-ops for now because we don't have a navigation bar here
39+
override fun minimizePlayerContainerLayout() {}
40+
41+
override fun maximizePlayerContainerLayout() {}
42+
43+
override fun setPlayerContainerProgress(progress: Float) {}
44+
45+
override fun clearSearchViewFocus(): Boolean = true
2546
}

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

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,13 @@ import com.github.libretube.helpers.AudioHelper
4040
import com.github.libretube.helpers.BackgroundHelper
4141
import com.github.libretube.helpers.ClipboardHelper
4242
import com.github.libretube.helpers.ImageHelper
43-
import com.github.libretube.helpers.NavBarHelper
4443
import com.github.libretube.helpers.NavigationHelper
4544
import com.github.libretube.helpers.PlayerHelper
4645
import com.github.libretube.helpers.ThemeHelper
4746
import com.github.libretube.services.AbstractPlayerService
4847
import com.github.libretube.services.OfflinePlayerService
4948
import com.github.libretube.services.OnlinePlayerService
50-
import com.github.libretube.ui.activities.MainActivity
51-
import com.github.libretube.ui.base.BaseActivity
49+
import com.github.libretube.ui.activities.AbstractPlayerHostActivity
5250
import com.github.libretube.ui.extensions.getSystemInsets
5351
import com.github.libretube.ui.extensions.setOnBackPressed
5452
import com.github.libretube.ui.interfaces.AudioPlayerOptions
@@ -63,17 +61,15 @@ import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
6361
import com.github.libretube.util.DataSaverMode
6462
import com.github.libretube.util.PlayingQueue
6563
import kotlinx.coroutines.launch
66-
import kotlin.math.abs
64+
import kotlin.math.absoluteValue
6765

6866
@UnstableApi
6967
class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlayerOptions {
7068
private var _binding: FragmentAudioPlayerBinding? = null
7169
val binding get() = _binding!!
7270

7371
private lateinit var audioHelper: AudioHelper
74-
private val activity get() = context as BaseActivity
75-
private val mainActivity get() = activity as? MainActivity
76-
private val mainActivityMotionLayout get() = mainActivity?.binding?.mainMotionLayout
72+
private val activity get() = context as AbstractPlayerHostActivity
7773
private val viewModel: CommonPlayerViewModel by activityViewModels()
7874
private val chaptersModel: ChaptersViewModel by activityViewModels()
7975

@@ -138,7 +134,7 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
138134
}
139135

140136
binding.minimizePlayer.setOnClickListener {
141-
mainActivityMotionLayout?.transitionToStart()
137+
activity.minimizePlayerContainerLayout()
142138
binding.playerMotionLayout.transitionToEnd()
143139
}
144140

@@ -245,8 +241,8 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
245241
override fun handleOnBackPressed() {
246242
binding.audioPlayerContainer.isClickable = false
247243
binding.playerMotionLayout.transitionToEnd()
248-
mainActivityMotionLayout?.transitionToEnd()
249-
mainActivity?.requestOrientationChange()
244+
activity.minimizePlayerContainerLayout()
245+
activity.requestOrientationChange()
250246
}
251247

252248
override fun handleOnBackProgressed(backEvent: BackEventCompat) {
@@ -310,7 +306,7 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
310306

311307
@SuppressLint("ClickableViewAccessibility")
312308
private fun initializeTransitionLayout() {
313-
mainActivityMotionLayout?.progress = 0F
309+
activity.setPlayerContainerProgress(0f)
314310

315311
binding.playerMotionLayout.addTransitionListener(object : TransitionAdapter() {
316312
override fun onTransitionChange(
@@ -319,22 +315,18 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
319315
endId: Int,
320316
progress: Float
321317
) {
322-
if (NavBarHelper.hasTabs()) {
323-
mainActivityMotionLayout?.progress = abs(progress)
324-
}
318+
activity.setPlayerContainerProgress(progress.absoluteValue)
325319
transitionEndId = endId
326320
transitionStartId = startId
327321
}
328322

329323
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
330324
if (currentId == transitionEndId) {
331325
viewModel.isMiniPlayerVisible.value = true
332-
if (NavBarHelper.hasTabs()) {
333-
mainActivityMotionLayout?.progress = 1F
334-
}
326+
activity.minimizePlayerContainerLayout()
335327
} else if (currentId == transitionStartId) {
336328
viewModel.isMiniPlayerVisible.value = false
337-
mainActivityMotionLayout?.progress = 0F
329+
activity.maximizePlayerContainerLayout()
338330
}
339331
}
340332
})
@@ -468,10 +460,6 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
468460
playerController?.mediaMetadata?.let { updateStreamInfo(it) }
469461

470462
initializeSeekBar()
471-
472-
if (isOffline) {
473-
binding.openVideo.isGone = true
474-
}
475463
}
476464

477465
override fun onDestroyView() {

0 commit comments

Comments
 (0)