mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-12 21:30:30 +05:30
Merge pull request #6863 from Bnyro/master
feat: support for predictive back gestures
This commit is contained in:
commit
0760a38ad2
@ -125,7 +125,7 @@ object NavBarHelper {
|
||||
return if (pref == Int.MAX_VALUE) {
|
||||
getNavBarItems(context).firstOrNull { it.isVisible }?.itemId ?: R.id.homeFragment
|
||||
} else {
|
||||
defaultNavItems.get(pref).itemId
|
||||
defaultNavItems[pref].itemId
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.ScrollView
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.ColorInt
|
||||
@ -22,7 +21,6 @@ import androidx.core.os.bundleOf
|
||||
import androidx.core.view.allViews
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isNotEmpty
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
@ -38,7 +36,6 @@ import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.databinding.ActivityMainBinding
|
||||
import com.github.libretube.enums.ImportFormat
|
||||
import com.github.libretube.extensions.anyChildFocused
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.helpers.ImportHelper
|
||||
import com.github.libretube.helpers.IntentHelper
|
||||
@ -54,17 +51,14 @@ import com.github.libretube.ui.dialogs.ImportTempPlaylistDialog
|
||||
import com.github.libretube.ui.fragments.AudioPlayerFragment
|
||||
import com.github.libretube.ui.fragments.DownloadsFragment
|
||||
import com.github.libretube.ui.fragments.PlayerFragment
|
||||
import com.github.libretube.ui.models.CommonPlayerViewModel
|
||||
import com.github.libretube.ui.models.SearchViewModel
|
||||
import com.github.libretube.ui.models.SubscriptionsViewModel
|
||||
import com.github.libretube.ui.preferences.BackupRestoreSettings.Companion.FILETYPE_ANY
|
||||
import com.github.libretube.ui.preferences.BackupRestoreSettings.Companion.JSON
|
||||
import com.github.libretube.util.UpdateChecker
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import kotlin.math.exp
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
lateinit var binding: ActivityMainBinding
|
||||
@ -74,7 +68,6 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
private var startFragmentId = R.id.homeFragment
|
||||
|
||||
private val commonPlayerViewModel: CommonPlayerViewModel by viewModels()
|
||||
private val searchViewModel: SearchViewModel by viewModels()
|
||||
private val subscriptionsViewModel: SubscriptionsViewModel by viewModels()
|
||||
|
||||
@ -185,44 +178,6 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
setupSubscriptionsBadge()
|
||||
|
||||
onBackPressedDispatcher.addCallback {
|
||||
if (commonPlayerViewModel.isFullscreen.value == true) {
|
||||
val fullscreenUnsetSuccess = runOnPlayerFragment {
|
||||
unsetFullscreen()
|
||||
true
|
||||
}
|
||||
if (fullscreenUnsetSuccess) return@addCallback
|
||||
}
|
||||
|
||||
if (binding.mainMotionLayout.progress == 0F) {
|
||||
runCatching {
|
||||
minimizePlayer()
|
||||
return@addCallback
|
||||
}
|
||||
}
|
||||
|
||||
when (navController.currentDestination?.id) {
|
||||
startFragmentId -> {
|
||||
moveTaskToBack(true)
|
||||
onUserLeaveHint()
|
||||
}
|
||||
|
||||
R.id.searchFragment -> {
|
||||
if (searchView.anyChildFocused()) searchView.clearFocus()
|
||||
else navController.popBackStack()
|
||||
}
|
||||
|
||||
R.id.searchResultFragment -> {
|
||||
navController.popBackStack(R.id.searchFragment, true) ||
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
else -> {
|
||||
navController.popBackStack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadIntentData()
|
||||
}
|
||||
|
||||
@ -407,13 +362,8 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
||||
if (binding.mainMotionLayout.progress == 0F) {
|
||||
runCatching {
|
||||
minimizePlayer()
|
||||
}
|
||||
}
|
||||
// Handover back press to `BackPressedDispatcher`
|
||||
else if (binding.bottomNav.menu.children.none {
|
||||
if (binding.bottomNav.menu.children.none {
|
||||
it.itemId == navController.currentDestination?.id
|
||||
}
|
||||
) {
|
||||
@ -591,25 +541,6 @@ class MainActivity : BaseActivity() {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun minimizePlayer() {
|
||||
binding.mainMotionLayout.transitionToEnd()
|
||||
supportFragmentManager.fragments.forEach { fragment ->
|
||||
(fragment as? PlayerFragment)?.binding?.apply {
|
||||
mainContainer.isClickable = false
|
||||
linLayout.isVisible = true
|
||||
playerMotionLayout.setTransitionDuration(250)
|
||||
playerMotionLayout.transitionToEnd()
|
||||
playerMotionLayout.enableTransition(R.id.yt_transition, true)
|
||||
}
|
||||
(fragment as? AudioPlayerFragment)?.binding?.apply {
|
||||
audioPlayerContainer.isClickable = false
|
||||
playerMotionLayout.transitionToEnd()
|
||||
}
|
||||
}
|
||||
|
||||
requestOrientationChange()
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
|
@ -2,67 +2,22 @@ package com.github.libretube.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.addCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.fragment.app.replace
|
||||
import androidx.navigation.findNavController
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.databinding.ActivityNointernetBinding
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.NetworkHelper
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.fragments.AudioPlayerFragment
|
||||
import com.github.libretube.ui.fragments.DownloadsFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
class NoInternetActivity : BaseActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val binding = ActivityNointernetBinding.inflate(layoutInflater)
|
||||
// retry button
|
||||
binding.retryButton.setOnClickListener {
|
||||
if (NetworkHelper.isNetworkAvailable(this)) {
|
||||
NavigationHelper.restartMainActivity(this)
|
||||
} else {
|
||||
Snackbar.make(binding.root, R.string.turnInternetOn, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
binding.noInternetSettingsImageView.setOnClickListener {
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.downloads.setOnClickListener {
|
||||
supportFragmentManager.commit {
|
||||
replace<DownloadsFragment>(R.id.container)
|
||||
addToBackStack(null)
|
||||
}
|
||||
}
|
||||
|
||||
setContentView(binding.root)
|
||||
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
if (removeFragment<DownloadsFragment>() || removeFragment<AudioPlayerFragment>()) return@addCallback
|
||||
|
||||
finishAffinity()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T: Fragment> removeFragment(): Boolean {
|
||||
val fragment = supportFragmentManager.fragments.filterIsInstance<T>()
|
||||
.firstOrNull()
|
||||
|
||||
if (fragment != null) {
|
||||
supportFragmentManager.commit {
|
||||
remove(fragment)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
val navController = findNavController(R.id.container)
|
||||
navController.graph = navController.navInflater.inflate(R.navigation.nav_nointernet)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.github.libretube.ui.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.addCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.fragment.app.replace
|
||||
@ -26,22 +25,17 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
redirectTo<MainSettings>()
|
||||
}
|
||||
|
||||
// new way of dealing with back presses instead of onBackPressed()
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
if (supportFragmentManager.findFragmentById(R.id.settings) is MainSettings) {
|
||||
finishAndRemoveTask()
|
||||
} else {
|
||||
redirectTo<MainSettings>()
|
||||
changeTopBarText(getString(R.string.settings))
|
||||
}
|
||||
goToMainSettings()
|
||||
}
|
||||
|
||||
handleRedirect()
|
||||
}
|
||||
|
||||
fun goToMainSettings() {
|
||||
redirectTo<MainSettings>()
|
||||
changeTopBarText(getString(R.string.settings))
|
||||
}
|
||||
|
||||
private fun handleRedirect() {
|
||||
val redirectKey = intent.extras?.getString(REDIRECT_KEY)
|
||||
|
||||
|
@ -19,6 +19,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
|
||||
abstract val titleResourceId: Int
|
||||
|
||||
private val settingsActivity get() = activity as? SettingsActivity
|
||||
|
||||
/**
|
||||
* Whether any preference dialog is currently visible to the user.
|
||||
*/
|
||||
@ -26,7 +28,8 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
(activity as? SettingsActivity)?.changeTopBarText(getString(titleResourceId))
|
||||
|
||||
settingsActivity?.changeTopBarText(getString(titleResourceId))
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.github.libretube.ui.extensions
|
||||
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
fun Fragment.setOnBackPressed(action: OnBackPressedCallback.() -> Unit): OnBackPressedCallback {
|
||||
val callback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
requireActivity().onBackPressedDispatcher.addCallback(
|
||||
viewLifecycleOwner,
|
||||
callback
|
||||
)
|
||||
|
||||
return callback
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.github.libretube.ui.extensions
|
||||
|
||||
import android.view.View
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.view.animation.PathInterpolatorCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
||||
private val GestureInterpolator = PathInterpolatorCompat.create(0f, 0f, 0f, 1f)
|
||||
|
||||
/**
|
||||
* Set a fragment animation to be displayed when swiping back as well as an [onBackPressed] action
|
||||
* that is executed when the back press was confirmed and not cancelled by the user
|
||||
*
|
||||
* @see <a href="https://github.com/android/animation-samples/blob/main/Motion/app/src/main/java/com/example/android/motion/demo/containertransform/CheeseArticleFragment.kt">Android animation samples</a>
|
||||
*/
|
||||
fun Fragment.setupFragmentAnimation(
|
||||
background: View, onBackPressed: () -> Unit = {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
) {
|
||||
val predictiveBackMargin = 50f
|
||||
var initialTouchY = -1f
|
||||
|
||||
val callback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun handleOnBackProgressed(backEvent: BackEventCompat) {
|
||||
val progress = GestureInterpolator.getInterpolation(backEvent.progress)
|
||||
if (initialTouchY < 0f) {
|
||||
initialTouchY = backEvent.touchY
|
||||
}
|
||||
val progressY = GestureInterpolator.getInterpolation(
|
||||
(backEvent.touchY - initialTouchY) / background.height
|
||||
)
|
||||
|
||||
// See the motion spec about the calculations below.
|
||||
// https://developer.android.com/design/ui/mobile/guides/patterns/predictive-back#motion-specs
|
||||
|
||||
// Shift horizontally.
|
||||
val maxTranslationX = (background.width / 20) - predictiveBackMargin
|
||||
background.translationX = progress * maxTranslationX *
|
||||
(if (backEvent.swipeEdge == BackEventCompat.EDGE_LEFT) 1 else -1)
|
||||
|
||||
// Shift vertically.
|
||||
val maxTranslationY = (background.height / 20) - predictiveBackMargin
|
||||
background.translationY = progressY * maxTranslationY
|
||||
|
||||
// Scale down from 100% to 90%.
|
||||
val scale = 1f - (0.1f * progress)
|
||||
background.scaleX = scale
|
||||
background.scaleY = scale
|
||||
}
|
||||
|
||||
override fun handleOnBackCancelled() {
|
||||
initialTouchY = -1f
|
||||
background.run {
|
||||
translationX = 0f
|
||||
translationY = 0f
|
||||
scaleX = 1f
|
||||
scaleY = 1f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
|
||||
}
|
@ -47,6 +47,7 @@ import com.github.libretube.services.OfflinePlayerService
|
||||
import com.github.libretube.services.OnlinePlayerService
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.extensions.setOnBackPressed
|
||||
import com.github.libretube.ui.interfaces.AudioPlayerOptions
|
||||
import com.github.libretube.ui.listeners.AudioPlayerThumbnailListener
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
@ -238,6 +239,17 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
if (!PlayerHelper.playAutomatically) updatePlayPauseButton()
|
||||
|
||||
updateChapterIndex()
|
||||
|
||||
val onBackPressedCallback = setOnBackPressed {
|
||||
binding.audioPlayerContainer.isClickable = false
|
||||
binding.playerMotionLayout.transitionToEnd()
|
||||
mainActivity?.binding?.mainMotionLayout?.transitionToEnd()
|
||||
mainActivity?.requestOrientationChange()
|
||||
}
|
||||
viewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible ->
|
||||
// if the player is minimized, the fragment behind the player should handle the event
|
||||
onBackPressedCallback.isEnabled = isMiniPlayerVisible != true
|
||||
}
|
||||
}
|
||||
|
||||
private fun killFragment() {
|
||||
|
@ -31,6 +31,7 @@ import com.github.libretube.obj.ShareData
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||
import com.github.libretube.ui.sheets.AddChannelToGroupSheet
|
||||
import com.github.libretube.util.deArrow
|
||||
@ -103,6 +104,8 @@ class ChannelFragment : DynamicLayoutManagerFragment() {
|
||||
}
|
||||
|
||||
fetchChannel()
|
||||
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
|
||||
// adjust sensitivity due to the issue of viewpager2 with SwipeToRefresh https://issuetracker.google.com/issues/138314213
|
||||
|
@ -34,6 +34,7 @@ import com.github.libretube.extensions.serializable
|
||||
import com.github.libretube.extensions.setOnDismissListener
|
||||
import com.github.libretube.helpers.BackgroundHelper
|
||||
import com.github.libretube.helpers.DownloadHelper
|
||||
import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.obj.DownloadStatus
|
||||
@ -41,6 +42,7 @@ import com.github.libretube.receivers.DownloadReceiver
|
||||
import com.github.libretube.services.DownloadService
|
||||
import com.github.libretube.ui.adapters.DownloadsAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -82,6 +84,10 @@ class DownloadsFragment : Fragment() {
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
}.attach()
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.downloadsFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
fun bindDownloadService() {
|
||||
|
@ -23,12 +23,14 @@ import com.github.libretube.constants.PreferenceKeys.HOME_TAB_CONTENT
|
||||
import com.github.libretube.databinding.FragmentHomeBinding
|
||||
import com.github.libretube.db.DatabaseHelper
|
||||
import com.github.libretube.db.obj.PlaylistBookmark
|
||||
import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.activities.SettingsActivity
|
||||
import com.github.libretube.ui.adapters.PlaylistBookmarkAdapter
|
||||
import com.github.libretube.ui.adapters.PlaylistsAdapter
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.adapters.VideosAdapter.Companion.LayoutMode
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.HomeViewModel
|
||||
import com.github.libretube.ui.models.SubscriptionsViewModel
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
@ -84,6 +86,10 @@ class HomeFragment : Fragment() {
|
||||
binding.changeInstance.setOnClickListener {
|
||||
redirectToIntentSettings()
|
||||
}
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.homeFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -35,6 +35,7 @@ import com.github.libretube.ui.adapters.PlaylistsAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.dialogs.CreatePlaylistDialog
|
||||
import com.github.libretube.ui.dialogs.CreatePlaylistDialog.Companion.CREATE_PLAYLIST_DIALOG_REQUEST_KEY
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.CommonPlayerViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -131,6 +132,10 @@ class LibraryFragment : DynamicLayoutManagerFragment() {
|
||||
}
|
||||
}.show(childFragmentManager)
|
||||
}
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.libraryFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.github.libretube.ui.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.databinding.FragmentNointernetBinding
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.NetworkHelper
|
||||
import com.github.libretube.ui.activities.SettingsActivity
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
class NoInternetFragment: Fragment() {
|
||||
private var _binding: FragmentNointernetBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentNointernetBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.retryButton.setOnClickListener {
|
||||
if (NetworkHelper.isNetworkAvailable(requireContext())) {
|
||||
NavigationHelper.restartMainActivity(requireContext())
|
||||
} else {
|
||||
Snackbar.make(binding.root, R.string.turnInternetOn, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
binding.noInternetSettingsImageView.setOnClickListener {
|
||||
val intent = Intent(requireContext(), SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.downloads.setOnClickListener {
|
||||
findNavController().navigate(R.id.downloadsFragment)
|
||||
}
|
||||
}
|
||||
}
|
@ -95,6 +95,7 @@ import com.github.libretube.ui.dialogs.AddToPlaylistDialog
|
||||
import com.github.libretube.ui.dialogs.PlayOfflineDialog
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.extensions.animateDown
|
||||
import com.github.libretube.ui.extensions.setOnBackPressed
|
||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||
import com.github.libretube.ui.interfaces.OnlinePlayerOptions
|
||||
import com.github.libretube.ui.listeners.SeekbarPreviewListener
|
||||
@ -459,6 +460,20 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
} else {
|
||||
attachToPlayerService(playerData, createNewSession)
|
||||
}
|
||||
|
||||
val onBackPressedCallback = setOnBackPressed {
|
||||
if (commonPlayerViewModel.isFullscreen.value == true) unsetFullscreen()
|
||||
else {
|
||||
binding.playerMotionLayout.setTransitionDuration(250)
|
||||
binding.playerMotionLayout.transitionToEnd()
|
||||
mainActivity.binding.mainMotionLayout.transitionToEnd()
|
||||
mainActivity.requestOrientationChange()
|
||||
}
|
||||
}
|
||||
commonPlayerViewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) { isMiniPlayerVisible ->
|
||||
// if the player is minimized, the fragment behind the player should handle the event
|
||||
onBackPressedCallback.isEnabled = isMiniPlayerVisible != true
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachToPlayerService(playerData: PlayerData, startNewSession: Boolean) {
|
||||
|
@ -41,6 +41,7 @@ import com.github.libretube.ui.adapters.PlaylistAdapter
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.addOnBottomReachedListener
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.CommonPlayerViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||
@ -119,6 +120,8 @@ class PlaylistFragment : DynamicLayoutManagerFragment() {
|
||||
})
|
||||
|
||||
fetchPlaylist()
|
||||
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -12,6 +12,7 @@ import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.paging.LoadState
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
@ -26,6 +27,7 @@ import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.adapters.SearchResultsAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.setOnBackPressed
|
||||
import com.github.libretube.ui.models.SearchResultViewModel
|
||||
import com.github.libretube.util.TextUtils.toTimeInSeconds
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -112,6 +114,11 @@ class SearchResultFragment : DynamicLayoutManagerFragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setOnBackPressed {
|
||||
findNavController().popBackStack(R.id.searchFragment, true) ||
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addToHistory(query: String) {
|
||||
|
@ -10,6 +10,7 @@ import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.constants.IntentData
|
||||
@ -17,10 +18,12 @@ import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.databinding.FragmentSearchSuggestionsBinding
|
||||
import com.github.libretube.db.DatabaseHolder.Database
|
||||
import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.extensions.anyChildFocused
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.adapters.SearchHistoryAdapter
|
||||
import com.github.libretube.ui.adapters.SearchSuggestionsAdapter
|
||||
import com.github.libretube.ui.extensions.setOnBackPressed
|
||||
import com.github.libretube.ui.models.SearchViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -30,6 +33,7 @@ class SearchSuggestionsFragment : Fragment() {
|
||||
private var _binding: FragmentSearchSuggestionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val viewModel: SearchViewModel by activityViewModels()
|
||||
private val mainActivity get() = activity as MainActivity
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -57,6 +61,11 @@ class SearchSuggestionsFragment : Fragment() {
|
||||
viewModel.searchQuery.observe(viewLifecycleOwner) {
|
||||
showData(it)
|
||||
}
|
||||
|
||||
setOnBackPressed {
|
||||
if (mainActivity.searchView.anyChildFocused()) mainActivity.searchView.clearFocus()
|
||||
else findNavController().popBackStack()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showData(query: String?) {
|
||||
|
@ -29,6 +29,7 @@ import com.github.libretube.db.DatabaseHolder
|
||||
import com.github.libretube.extensions.dpToPx
|
||||
import com.github.libretube.extensions.formatShort
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.obj.SelectableOption
|
||||
@ -37,8 +38,9 @@ import com.github.libretube.ui.adapters.SubscriptionChannelAdapter
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.addOnBottomReachedListener
|
||||
import com.github.libretube.ui.models.EditChannelGroupsModel
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.CommonPlayerViewModel
|
||||
import com.github.libretube.ui.models.EditChannelGroupsModel
|
||||
import com.github.libretube.ui.models.SubscriptionsViewModel
|
||||
import com.github.libretube.ui.sheets.ChannelGroupsSheet
|
||||
import com.github.libretube.ui.sheets.FilterSortBottomSheet
|
||||
@ -203,6 +205,10 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
.sortedBy { it.index }
|
||||
channelGroupsModel.groups.postValue(groups)
|
||||
}
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.subscriptionsFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadNextFeedItems() {
|
||||
|
@ -11,9 +11,11 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.databinding.FragmentTrendsBinding
|
||||
import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.ui.activities.SettingsActivity
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.TrendsViewModel
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
@ -70,6 +72,10 @@ class TrendsFragment : DynamicLayoutManagerFragment() {
|
||||
})
|
||||
|
||||
viewModel.fetchTrending(requireContext())
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.trendsFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
|
@ -27,12 +27,14 @@ import com.github.libretube.db.obj.WatchHistoryItem
|
||||
import com.github.libretube.extensions.ceilHalf
|
||||
import com.github.libretube.extensions.dpToPx
|
||||
import com.github.libretube.extensions.setOnDismissListener
|
||||
import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.helpers.ProxyHelper
|
||||
import com.github.libretube.ui.adapters.WatchHistoryAdapter
|
||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||
import com.github.libretube.ui.extensions.addOnBottomReachedListener
|
||||
import com.github.libretube.ui.extensions.setupFragmentAnimation
|
||||
import com.github.libretube.ui.models.CommonPlayerViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
@ -159,6 +161,10 @@ class WatchHistoryFragment : DynamicLayoutManagerFragment() {
|
||||
|
||||
showWatchHistory(history)
|
||||
}
|
||||
|
||||
if (NavBarHelper.getStartFragmentId(requireContext()) != R.id.watchHistoryFragment) {
|
||||
setupFragmentAnimation(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showWatchHistory(history: List<WatchHistoryItem>) {
|
||||
|
@ -1,66 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/noInternet_settingsImageView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_margin="16dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/middle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/noInternet_imageView"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_no_wifi" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noInternet_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/noInternet" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/retry_button"
|
||||
style="@style/ThemeOverlay.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/retry"
|
||||
android:textColor="?android:attr/colorBackground"
|
||||
app:elevation="20dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/downloads"
|
||||
style="@style/ThemeOverlay.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/downloads"
|
||||
android:textColor="?android:attr/colorBackground"
|
||||
app:elevation="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
<fragment
|
||||
android:id="@+id/container"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:elevation="20dp"
|
||||
|
61
app/src/main/res/layout/fragment_nointernet.xml
Normal file
61
app/src/main/res/layout/fragment_nointernet.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/noInternet_settingsImageView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_margin="16dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/middle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/noInternet_imageView"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_no_wifi" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noInternet_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/noInternet" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/retry_button"
|
||||
style="@style/ThemeOverlay.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/retry"
|
||||
android:textColor="?android:attr/colorBackground"
|
||||
app:elevation="20dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/downloads"
|
||||
style="@style/ThemeOverlay.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/downloads"
|
||||
android:textColor="?android:attr/colorBackground"
|
||||
app:elevation="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
18
app/src/main/res/navigation/nav_nointernet.xml
Normal file
18
app/src/main/res/navigation/nav_nointernet.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/nav_noInternet"
|
||||
app:startDestination="@id/noInternetFragment">
|
||||
<fragment
|
||||
android:id="@+id/noInternetFragment"
|
||||
android:name="com.github.libretube.ui.fragments.NoInternetFragment"
|
||||
android:label="fragment_nointernet"
|
||||
tools:layout="@layout/fragment_nointernet" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/downloadsFragment"
|
||||
android:name="com.github.libretube.ui.fragments.DownloadsFragment"
|
||||
android:label="@string/downloads"
|
||||
tools:layout="@layout/fragment_downloads" />
|
||||
</navigation>
|
Loading…
Reference in New Issue
Block a user