Bug 1813794: Save search results when navigating back from saved logins list

fenix/123.0
alexandra.virvara 6 months ago committed by mergify[bot]
parent b3fcbcbc56
commit 45e873fa01

@ -607,14 +607,12 @@ class LoginsTest {
revealPassword()
verifyPasswordSaved("firefox")
}.goBackToSavedLogins {
clickSearchLoginButton()
searchLogin("android")
viewSavedLoginDetails(originWebsite)
verifyLoginItemUsername("android")
revealPassword()
verifyPasswordSaved("firefox")
}.goBackToSavedLogins {
clickSearchLoginButton()
searchLogin("AnDrOiD")
viewSavedLoginDetails(originWebsite)
verifyLoginItemUsername("android")
@ -654,14 +652,12 @@ class LoginsTest {
revealPassword()
verifyPasswordSaved("firefox")
}.goBackToSavedLogins {
clickSearchLoginButton()
searchLogin("mozilla")
viewSavedLoginDetails(originWebsite)
verifyLoginItemUsername("android")
revealPassword()
verifyPasswordSaved("firefox")
}.goBackToSavedLogins {
clickSearchLoginButton()
searchLogin("MoZiLlA")
viewSavedLoginDetails(originWebsite)
verifyLoginItemUsername("android")

@ -118,7 +118,7 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot {
)
fun searchLogin(searchTerm: String) =
itemContainingText(getStringResource(R.string.preferences_passwords_saved_logins_search)).setText(searchTerm)
itemWithResId("$packageName:id/search").setText(searchTerm)
fun verifySavedLoginsSectionUsername(username: String) =
mDevice.waitNotNull(Until.findObjects(By.text(username)))

@ -22,6 +22,7 @@ import org.mozilla.fenix.utils.Settings
* @param loginsFragmentStore Store used to hold in-memory collection state.
* @param navController NavController manages app navigation within a NavHost.
* @param browserNavigator Controller allowing browser navigation to any Uri.
* @param addLoginCallback Callback used for add login
* @param settings SharedPreferences wrapper for easier usage.
*/
class LoginsListController(
@ -32,6 +33,7 @@ class LoginsListController(
newTab: Boolean,
from: BrowserDirection,
) -> Unit,
private val addLoginCallback: () -> Unit,
private val settings: Settings,
) {
@ -46,6 +48,7 @@ class LoginsListController(
fun handleAddLoginClicked() {
Logins.managementAddTapped.record(NoExtras())
addLoginCallback.invoke()
navController.navigate(
SavedLoginsFragmentDirections.actionSavedLoginsFragmentToAddLoginFragment(),
)

@ -14,8 +14,12 @@ import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.activity.addCallback
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import androidx.core.view.MenuProvider
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
@ -108,6 +112,16 @@ class LoginDetailFragment : SecureFragment(R.layout.fragment_login_detail), Menu
setUpPasswordReveal()
}
togglePasswordReveal(binding.passwordText, binding.revealPasswordButton)
setFragmentResultListener(HAS_QUERY_KEY) { _, bundle ->
val hasSearchQuery = bundle.getString(HAS_QUERY_BUNDLE)
if (hasSearchQuery == null) {
requireActivity().onBackPressedDispatcher.addCallback(this) {
val directions = LoginDetailFragmentDirections.actionLoginDetailFragmentToSavedLogins()
findNavController().navigate(directions)
}
}
}
}
/**
@ -219,6 +233,12 @@ class LoginDetailFragment : SecureFragment(R.layout.fragment_login_detail), Menu
Logins.deleteSavedLogin.record(NoExtras())
Logins.deleted.add()
interactor.onDeleteLogin(args.savedLoginId)
setFragmentResult(
LOGIN_REQUEST_KEY,
bundleOf(LOGIN_BUNDLE_ARGS to args.savedLoginId),
)
dialog.dismiss()
}
create().withCenterAlignedButtons()
@ -233,5 +253,10 @@ class LoginDetailFragment : SecureFragment(R.layout.fragment_login_detail), Menu
companion object {
private const val BUTTON_INCREASE_DPS = 24
const val LOGIN_REQUEST_KEY = "logins"
const val LOGIN_BUNDLE_ARGS = "loginsBundle"
const val HAS_QUERY_KEY = "hasSearchQueryKey"
const val HAS_QUERY_BUNDLE = "hasSearchQueryBundle"
}
}

@ -13,11 +13,15 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.core.view.MenuProvider
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
@ -36,6 +40,7 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.logins.LoginsAction
import org.mozilla.fenix.settings.logins.LoginsFragmentStore
import org.mozilla.fenix.settings.logins.LoginsListState
import org.mozilla.fenix.settings.logins.SavedLoginsSortingStrategyMenu
import org.mozilla.fenix.settings.logins.SortingStrategy
import org.mozilla.fenix.settings.logins.controller.LoginsListController
@ -56,6 +61,11 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
private lateinit var loginsListController: LoginsListController
private lateinit var savedLoginsStorageController: SavedLoginsStorageController
private lateinit var loginState: LoginsListState
private var removedLoginGuid: String? = null
private var deletedGuid = mutableSetOf<String>()
private var searchQuery: LoginsListState? = null
override fun onResume() {
super.onResume()
initToolbar()
@ -81,6 +91,9 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
loginsFragmentStore = savedLoginsStore,
navController = findNavController(),
browserNavigator = ::openToBrowserAndLoad,
addLoginCallback = {
searchQuery = null
},
settings = requireContext().settings(),
)
savedLoginsStorageController =
@ -107,9 +120,24 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
consumeFrom(savedLoginsStore) {
setFragmentResultListener(LoginDetailFragment.LOGIN_REQUEST_KEY) { _, bundle ->
removedLoginGuid = bundle.getString(LoginDetailFragment.LOGIN_BUNDLE_ARGS)
deletedGuid.add(removedLoginGuid.toString())
}
consumeFrom(savedLoginsStore) { loginsListState ->
sortingStrategyMenu.updateMenu(savedLoginsStore.state.highlightedItem)
savedLoginsListView.update(it)
loginState = loginsListState
val currentList = loginState.filteredItems.toMutableList()
if (removedLoginGuid != null) {
val newList = currentList.filter { !deletedGuid.contains(it.guid) }
loginState = loginState.copy(
loginList = newList,
filteredItems = newList,
)
}
savedLoginsListView.update(loginState)
}
}
@ -121,6 +149,13 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
searchView.queryHint = getString(R.string.preferences_passwords_saved_logins_search)
searchView.maxWidth = Int.MAX_VALUE
if (searchQuery?.searchedForText?.isNotEmpty() == true) {
searchItem.expandActionView()
searchView.setQuery(searchQuery?.searchedForText, true)
searchView.clearFocus()
filterSavedLogins(searchQuery?.searchedForText)
}
searchView.setOnQueryTextListener(
object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
@ -128,15 +163,32 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
}
override fun onQueryTextChange(newText: String?): Boolean {
savedLoginsStore.dispatch(
LoginsAction.FilterLogins(
newText,
),
)
if (newText?.isNotEmpty() == true) {
searchQuery = savedLoginsStore.state.copy(
searchedForText = newText,
)
}
filterSavedLogins(newText)
return false
}
},
)
val closeButton: ImageView = searchView.findViewById(R.id.search_close_btn) as ImageView
closeButton.setOnClickListener {
searchView.setQuery("", false)
searchQuery = savedLoginsStore.state.copy(
searchedForText = null,
)
}
}
private fun filterSavedLogins(query: String?) {
savedLoginsStore.dispatch(
LoginsAction.FilterLogins(
query,
),
)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = false
@ -152,6 +204,11 @@ class SavedLoginsFragment : SecureFragment(), MenuProvider {
sortingStrategyMenu.menuController.dismiss()
sortLoginsMenuRoot.setOnClickListener(null)
setFragmentResult(
LoginDetailFragment.HAS_QUERY_KEY,
bundleOf(LoginDetailFragment.HAS_QUERY_BUNDLE to searchQuery?.searchedForText),
)
redirectToReAuth(
listOf(R.id.loginDetailFragment, R.id.addLoginFragment),
findNavController().currentDestination?.id,

@ -10,5 +10,5 @@
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:iconTint="?attr/textPrimary"
android:contentDescription="@string/preferences_passwords_saved_logins_search"
app:showAsAction="ifRoom|collapseActionView" />
app:showAsAction="collapseActionView|always" />
</menu>

@ -33,12 +33,14 @@ class LoginsListControllerTest {
private val sortingStrategy: SortingStrategy = SortingStrategy.Alphabetically
private val navController: NavController = mockk(relaxed = true)
private val browserNavigator: (String, Boolean, BrowserDirection) -> Unit = mockk(relaxed = true)
private val addLoginCallback: () -> Unit = mockk(relaxed = true)
private val controller =
LoginsListController(
loginsFragmentStore = store,
navController = navController,
browserNavigator = browserNavigator,
settings = settings,
addLoginCallback = addLoginCallback,
)
@Test

Loading…
Cancel
Save