diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 5d39f6554cd..d84005d0afa 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -194,6 +194,15 @@ import kotlin.math.absoluteValue import kotlin.reflect.full.createInstance import kotlin.system.exitProcess +internal fun shouldFocusSearchOnReselection( + currentDestinationId: Int?, + selectedDestinationId: Int, + isPhoneLayout: Boolean, +): Boolean = + isPhoneLayout && + currentDestinationId == R.id.navigation_search && + selectedDestinationId == R.id.navigation_search + class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCallback { companion object { var activityResultLauncher: ActivityResultLauncher? = null @@ -746,7 +755,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa hierarchy.any { it.id == destId } private var lastNavTime = 0L - private fun onNavDestinationSelected(item: MenuItem, navController: NavController): Boolean { + private fun onNavDestinationSelected( + item: MenuItem, + navController: NavController, + navHostFragment: NavHostFragment, + ): Boolean { val currentTime = System.currentTimeMillis() // safeDebounce: Check if a previous tap happened within the last 400ms if (currentTime - lastNavTime < 400) return false @@ -755,7 +768,14 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa val destinationId = item.itemId // Check if we are already at the selected destination - if (navController.currentDestination?.id == destinationId) return false + val currentDestinationId = navController.currentDestination?.id + if (shouldFocusSearchOnReselection(currentDestinationId, destinationId, isLayout(PHONE))) { + (navHostFragment.childFragmentManager.primaryNavigationFragment as? SearchFragment) + ?.focusSearchInput() + } + if (currentDestinationId == destinationId) { + return false + } // Make all nav buttons focus on this specific view when nextFocusRightId val targetView = when (destinationId) { @@ -1704,7 +1724,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa setOnItemSelectedListener { item -> onNavDestinationSelected( item, - navController + navController, + navHostFragment ) } @@ -1732,7 +1753,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa setOnItemSelectedListener { item -> onNavDestinationSelected( item, - navController + navController, + navHostFragment ) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 5f5b064b543..644e2c6c457 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -157,6 +157,10 @@ class SearchFragment : BaseFragment( afterPluginsLoadedEvent -= ::reloadRepos } + internal fun focusSearchInput() { + binding?.mainSearch?.requestFocusFromTouch() + } + var selectedSearchTypes = mutableListOf() var selectedApis = mutableSetOf() diff --git a/app/src/test/java/com/lagradost/cloudstream3/SearchNavigationTest.kt b/app/src/test/java/com/lagradost/cloudstream3/SearchNavigationTest.kt new file mode 100644 index 00000000000..6d62a083342 --- /dev/null +++ b/app/src/test/java/com/lagradost/cloudstream3/SearchNavigationTest.kt @@ -0,0 +1,51 @@ +package com.lagradost.cloudstream3 + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class SearchNavigationTest { + @Test + fun `phone search reselection requests focus`() { + assertTrue( + shouldFocusSearchOnReselection( + currentDestinationId = R.id.navigation_search, + selectedDestinationId = R.id.navigation_search, + isPhoneLayout = true, + ) + ) + } + + @Test + fun `tv search reselection keeps existing focus behavior`() { + assertFalse( + shouldFocusSearchOnReselection( + currentDestinationId = R.id.navigation_search, + selectedDestinationId = R.id.navigation_search, + isPhoneLayout = false, + ) + ) + } + + @Test + fun `first search selection does not request focus`() { + assertFalse( + shouldFocusSearchOnReselection( + currentDestinationId = R.id.navigation_home, + selectedDestinationId = R.id.navigation_search, + isPhoneLayout = true, + ) + ) + } + + @Test + fun `non-search reselection does not request focus`() { + assertFalse( + shouldFocusSearchOnReselection( + currentDestinationId = R.id.navigation_home, + selectedDestinationId = R.id.navigation_home, + isPhoneLayout = true, + ) + ) + } +}