2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-03 23:15:31 +00:00

Bug 1824379 - When adding a new login add it to the shared LoginsFragmentStore

This brings multiple advantages over the current implementation:
- we're not creating a new instance of SavedLoginsFragment
- we avoid a deeper and more expensive layer of caching the just added login
through SyncableLoginsStorage and use the in memory data.
- we avoid having to intercept the back press to control navigation
This commit is contained in:
Mugurell 2023-03-28 11:31:56 +03:00 committed by mergify[bot]
parent 066cdb7146
commit 52d035c13c
6 changed files with 34 additions and 17 deletions

View File

@ -53,6 +53,7 @@ class LoginsFragmentStore(initialState: LoginsListState) :
sealed class LoginsAction : Action {
data class FilterLogins(val newText: String?) : LoginsAction()
data class UpdateLoginsList(val list: List<SavedLogin>) : LoginsAction()
data class AddLogin(val newLogin: SavedLogin) : LoginsAction()
object LoginsListUpToDate : LoginsAction()
data class UpdateCurrentLogin(val item: SavedLogin) : LoginsAction()
data class SortLogins(val sortingStrategy: SortingStrategy) : LoginsAction()
@ -108,6 +109,14 @@ private fun savedLoginsStateReducer(
filteredItems = state.sortingStrategy(action.list),
)
}
is LoginsAction.AddLogin -> {
val updatedLogins = state.loginList + action.newLogin
state.copy(
isLoading = false,
loginList = updatedLogins,
filteredItems = state.sortingStrategy(updatedLogins),
)
}
is LoginsAction.FilterLogins -> {
filterItems(
action.newText,

View File

@ -98,7 +98,7 @@ open class SavedLoginsStorageController(
var encryptedLogin: EncryptedLogin? = null
try {
encryptedLogin = passwordsStorage.add(loginEntryToSave)
syncAndUpdateList(passwordsStorage.decryptLogin(encryptedLogin))
addLoginToState(passwordsStorage.decryptLogin(encryptedLogin))
} catch (loginException: LoginsApiException) {
Log.e(
"Add new login",
@ -149,7 +149,7 @@ open class SavedLoginsStorageController(
private suspend fun save(guid: String, loginEntryToSave: LoginEntry) {
try {
val encryptedLogin = passwordsStorage.update(guid, loginEntryToSave)
syncAndUpdateList(passwordsStorage.decryptLogin(encryptedLogin))
addLoginToState(passwordsStorage.decryptLogin(encryptedLogin))
} catch (loginException: LoginsApiException) {
when (loginException) {
is NoSuchRecordException,
@ -170,12 +170,10 @@ open class SavedLoginsStorageController(
}
}
private fun syncAndUpdateList(updatedLogin: Login) {
private fun addLoginToState(updatedLogin: Login) {
val login = updatedLogin.mapToSavedLogin()
loginsFragmentStore.dispatch(
LoginsAction.UpdateLoginsList(
listOf(login),
),
LoginsAction.AddLogin(login),
)
}

View File

@ -14,7 +14,6 @@ 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
@ -128,13 +127,6 @@ class LoginDetailFragment : SecureFragment(R.layout.fragment_login_detail), Menu
)
super.onPause()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireActivity().onBackPressedDispatcher.addCallback(this) {
val directions = LoginDetailFragmentDirections.actionLoginDetailFragmentToSavedLogins()
findNavController().navigate(directions)
}
}
private fun setUpPasswordReveal() {
binding.passwordText.inputType =

View File

@ -84,6 +84,23 @@ class LoginsFragmentStoreTest {
assertEquals(listOf(firefoxLogin, exampleLogin), store.state.filteredItems)
}
@Test
fun `GIVEN logins already exist WHEN asked to add a new one THEN update the state to contain them all`() {
val store = LoginsFragmentStore(
baseState.copy(isLoading = true),
)
store.dispatch(LoginsAction.AddLogin(exampleLogin)).joinBlocking()
assertFalse(store.state.isLoading)
assertEquals(listOf(exampleLogin), store.state.loginList)
// Select a login to force "isLoading = true"
store.dispatch(LoginsAction.AddLogin(firefoxLogin)).joinBlocking()
assertFalse(store.state.isLoading)
assertEquals(loginList, store.state.loginList)
assertEquals(listOf(firefoxLogin, exampleLogin), store.state.filteredItems)
}
@Test
fun `FilterLogins action`() {
val store = LoginsFragmentStore(

View File

@ -135,14 +135,14 @@ class SavedLoginsStorageControllerTest {
oldLogin.guid,
)
val expectedNewList = listOf(newLogin.mapToSavedLogin())
val expectedNewLogin = newLogin.mapToSavedLogin()
coVerify {
passwordsStorage.get(oldLogin.guid)
passwordsStorage.update(newLogin.guid, newLogin.toEntry())
loginsFragmentStore.dispatch(
LoginsAction.UpdateLoginsList(
expectedNewList,
LoginsAction.AddLogin(
expectedNewLogin,
),
)
navController.navigate(directionsEq(directions))

View File

@ -251,6 +251,7 @@
<ID>UndocumentedPublicClass:LoginsFragmentStore.kt$LoginsAction$SortLogins : LoginsAction</ID>
<ID>UndocumentedPublicClass:LoginsFragmentStore.kt$LoginsAction$UpdateCurrentLogin : LoginsAction</ID>
<ID>UndocumentedPublicClass:LoginsFragmentStore.kt$LoginsAction$UpdateLoginsList : LoginsAction</ID>
<ID>UndocumentedPublicClass:LoginsFragmentStore.kt$LoginsAction$AddLogin : LoginsAction</ID>
<ID>UndocumentedPublicClass:LoginsListViewHolder.kt$LoginsListViewHolder : ViewHolder</ID>
<ID>UndocumentedPublicClass:MenuPresenter.kt$MenuPresenter : OnAttachStateChangeListener</ID>
<ID>UndocumentedPublicClass:MessageMetadataStorage.kt$MessageMetadataStorage</ID>