diff --git a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt index a3c6f7cf1..08a00e62a 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt @@ -17,6 +17,7 @@ import android.view.WindowManager import androidx.activity.OnBackPressedCallback import androidx.appcompat.widget.SearchView import androidx.core.os.bundleOf +import androidx.core.view.children import androidx.lifecycle.ViewModelProvider import androidx.navigation.NavController import androidx.navigation.findNavController @@ -105,18 +106,16 @@ class MainActivity : BaseActivity() { binding.bottomNav.setOnApplyWindowInsetsListener(null) - binding.bottomNav.setOnItemSelectedListener { - // clear backstack if it's the start fragment - if (startFragmentId == it.itemId) navController.backQueue.clear() - - if (it.itemId == R.id.subscriptionsFragment) { - binding.bottomNav.removeBadge(R.id.subscriptionsFragment) + // Prevent duplicate entries into backstack, if selected item and current + // visible fragment is different, then navigate to selected item. + binding.bottomNav.setOnItemReselectedListener { + if (it.itemId != navController.currentDestination?.id) { + navigateToBottomSelectedItem(it) } + } - removeSearchFocus() - - // navigate to the selected fragment - navController.navigate(it.itemId) + binding.bottomNav.setOnItemSelectedListener { + navigateToBottomSelectedItem(it) false } @@ -144,10 +143,17 @@ class MainActivity : BaseActivity() { } } - if (navController.currentDestination?.id == startFragmentId) { - moveTaskToBack(true) - } else { - navController.popBackStack() + when (navController.currentDestination?.id) { + startFragmentId -> { + moveTaskToBack(true) + } + R.id.searchResultFragment -> { + navController.popBackStack(R.id.searchFragment, true) || + navController.popBackStack() + } + else -> { + navController.popBackStack() + } } } }) @@ -219,23 +225,26 @@ class MainActivity : BaseActivity() { val searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java] - searchView.setOnSearchClickListener { - if (navController.currentDestination?.id != R.id.searchResultFragment) { - searchViewModel.setQuery(null) - navController.navigate(R.id.searchFragment) - } - } - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { val bundle = Bundle() bundle.putString("query", query) navController.navigate(R.id.searchResultFragment, bundle) searchViewModel.setQuery("") + searchView.clearFocus() return true } override fun onQueryTextChange(newText: String?): Boolean { + // Prevent navigation when search view is collapsed + if (searchView.isIconified || + binding.bottomNav.menu.children.any { + it.itemId == navController.currentDestination?.id + } + ) { + return true + } + // prevent malicious navigation when the search view is getting collapsed if (navController.currentDestination?.id in listOf( R.id.searchResultFragment, @@ -258,6 +267,36 @@ class MainActivity : BaseActivity() { return true } }) + + searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem): Boolean { + if (navController.currentDestination?.id != R.id.searchResultFragment) { + searchViewModel.setQuery(null) + navController.navigate(R.id.searchFragment) + } + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS or MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) + return true + } + + override fun onMenuItemActionCollapse(item: MenuItem): Boolean { + if (binding.mainMotionLayout.progress == 0F) { + try { + minimizePlayer() + } catch (e: Exception) { + // current fragment isn't the player fragment + } + } + // Handover back press to `BackPressedDispatcher` + else if (binding.bottomNav.menu.children.none { + it.itemId == navController.currentDestination?.id + } + ) { + this@MainActivity.onBackPressedDispatcher.onBackPressed() + } + + return true + } + }) return super.onCreateOptionsMenu(menu) } @@ -450,6 +489,26 @@ class MainActivity : BaseActivity() { } } + private fun navigateToBottomSelectedItem(item: MenuItem) { + // clear backstack if it's the start fragment + if (startFragmentId == item.itemId) navController.backQueue.clear() + + if (item.itemId == R.id.subscriptionsFragment) { + binding.bottomNav.removeBadge(R.id.subscriptionsFragment) + } + + // navigate to the selected fragment, if the fragment already + // exists in backstack then pop up to that entry + if (!navController.popBackStack(item.itemId, false)) { + navController.navigate(item.itemId) + } + + // Remove focus from search view when navigating to bottom view. + // Call only after navigate to destination, so it can be used in + // onMenuItemActionCollapse for backstack management + removeSearchFocus() + } + override fun onUserLeaveHint() { super.onUserLeaveHint() supportFragmentManager.fragments.forEach { fragment -> diff --git a/app/src/main/java/com/github/libretube/ui/fragments/SearchResultFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/SearchResultFragment.kt index 780c29f1b..d85d39942 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/SearchResultFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/SearchResultFragment.kt @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import com.github.libretube.R import com.github.libretube.api.RetrofitInstance @@ -16,7 +15,6 @@ import com.github.libretube.db.DatabaseHelper import com.github.libretube.db.obj.SearchHistoryItem import com.github.libretube.extensions.TAG import com.github.libretube.extensions.hideKeyboard -import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.adapters.SearchAdapter import com.github.libretube.ui.base.BaseFragment import com.github.libretube.util.PreferenceHelper @@ -143,14 +141,4 @@ class SearchResultFragment : BaseFragment() { ) } } - - override fun onStop() { - if (findNavController().currentDestination?.id != R.id.searchFragment) { - // remove the search focus - (activity as MainActivity) - .binding.toolbar.menu - .findItem(R.id.action_search).collapseActionView() - } - super.onStop() - } }