mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
For #24856 - Toggle the "Manage addresses" and "Add address" preference label depending on whether there are saved addresses
This commit is contained in:
parent
d1c43761eb
commit
aff4c03d53
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package org.mozilla.fenix.settings.autofill
|
package org.mozilla.fenix.settings.autofill
|
||||||
|
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.concept.storage.CreditCard
|
import mozilla.components.concept.storage.CreditCard
|
||||||
import mozilla.components.lib.state.Action
|
import mozilla.components.lib.state.Action
|
||||||
import mozilla.components.lib.state.State
|
import mozilla.components.lib.state.State
|
||||||
@ -18,14 +19,16 @@ class AutofillFragmentStore(initialState: AutofillFragmentState) :
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state for [CreditCardsManagementFragment].
|
* The state used for managing autofill data.
|
||||||
*
|
*
|
||||||
|
* @property addresses The list of [Address]es to display in the address list.
|
||||||
* @property creditCards The list of [CreditCard]s to display in the credit card list.
|
* @property creditCards The list of [CreditCard]s to display in the credit card list.
|
||||||
* @property isLoading True if the credit cards are still being loaded from storage,
|
* @property isLoading True if the addresses or credit cards are still being loaded from storage,
|
||||||
* otherwise false.
|
* otherwise false.
|
||||||
*/
|
*/
|
||||||
data class AutofillFragmentState(
|
data class AutofillFragmentState(
|
||||||
val creditCards: List<CreditCard>,
|
val addresses: List<Address> = emptyList(),
|
||||||
|
val creditCards: List<CreditCard> = emptyList(),
|
||||||
val isLoading: Boolean = true
|
val isLoading: Boolean = true
|
||||||
) : State
|
) : State
|
||||||
|
|
||||||
@ -34,6 +37,13 @@ data class AutofillFragmentState(
|
|||||||
* through the [autofillFragmentStateReducer].
|
* through the [autofillFragmentStateReducer].
|
||||||
*/
|
*/
|
||||||
sealed class AutofillAction : Action {
|
sealed class AutofillAction : Action {
|
||||||
|
/**
|
||||||
|
* Updates the list of addresses with the provided [addresses].
|
||||||
|
*
|
||||||
|
* @param addresses The list of [Address]es to display in the address list.
|
||||||
|
*/
|
||||||
|
data class UpdateAddresses(val addresses: List<Address>) : AutofillAction()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the list of credit cards with the provided [creditCards].
|
* Updates the list of credit cards with the provided [creditCards].
|
||||||
*
|
*
|
||||||
@ -54,6 +64,12 @@ private fun autofillFragmentStateReducer(
|
|||||||
action: AutofillAction
|
action: AutofillAction
|
||||||
): AutofillFragmentState {
|
): AutofillFragmentState {
|
||||||
return when (action) {
|
return when (action) {
|
||||||
|
is AutofillAction.UpdateAddresses -> {
|
||||||
|
state.copy(
|
||||||
|
addresses = action.addresses,
|
||||||
|
isLoading = false
|
||||||
|
)
|
||||||
|
}
|
||||||
is AutofillAction.UpdateCreditCards -> {
|
is AutofillAction.UpdateCreditCards -> {
|
||||||
state.copy(
|
state.copy(
|
||||||
creditCards = action.creditCards,
|
creditCards = action.creditCards,
|
||||||
|
@ -25,6 +25,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import mozilla.components.lib.state.ext.consumeFrom
|
import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import mozilla.components.service.fxa.SyncEngine
|
import mozilla.components.service.fxa.SyncEngine
|
||||||
|
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
|
||||||
import org.mozilla.fenix.NavGraphDirections
|
import org.mozilla.fenix.NavGraphDirections
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.StoreProvider
|
import org.mozilla.fenix.components.StoreProvider
|
||||||
@ -46,7 +47,8 @@ import org.mozilla.fenix.settings.requirePreference
|
|||||||
class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
||||||
|
|
||||||
private lateinit var store: AutofillFragmentStore
|
private lateinit var store: AutofillFragmentStore
|
||||||
private var isCreditCardsListLoaded: Boolean = false
|
|
||||||
|
private var isAutofillStateLoaded: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of preferences to be enabled or disabled during authentication.
|
* List of preferences to be enabled or disabled during authentication.
|
||||||
@ -73,9 +75,9 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
store = StoreProvider.get(this) {
|
store = StoreProvider.get(this) {
|
||||||
AutofillFragmentStore(AutofillFragmentState(creditCards = emptyList()))
|
AutofillFragmentStore(AutofillFragmentState())
|
||||||
}
|
}
|
||||||
loadCreditCards()
|
loadAutofillState()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
@ -99,13 +101,17 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
loadCreditCards()
|
loadAutofillState()
|
||||||
return super.onCreateView(inflater, container, savedInstanceState)
|
return super.onCreateView(inflater, container, savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
consumeFrom(store) { state ->
|
consumeFrom(store) { state ->
|
||||||
|
if (requireComponents.settings.addressFeature) {
|
||||||
|
updateAddressPreference(state.addresses.isNotEmpty())
|
||||||
|
}
|
||||||
updateCardManagementPreference(state.creditCards.isNotEmpty(), findNavController())
|
updateCardManagementPreference(state.creditCards.isNotEmpty(), findNavController())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +120,7 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
isCreditCardsListLoaded = false
|
isAutofillStateLoaded = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -150,6 +156,25 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||||||
togglePrefsEnabled(creditCardPreferences, true)
|
togglePrefsEnabled(creditCardPreferences, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates preferences visibility depending on addresses being already saved or not.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
internal fun updateAddressPreference(hasAddresses: Boolean) {
|
||||||
|
val manageAddressesPreference =
|
||||||
|
requirePreference<Preference>(R.string.pref_key_addresses_manage_addresses)
|
||||||
|
|
||||||
|
if (hasAddresses) {
|
||||||
|
manageAddressesPreference.icon = null
|
||||||
|
manageAddressesPreference.title =
|
||||||
|
getString(R.string.preferences_addresses_manage_addresses)
|
||||||
|
} else {
|
||||||
|
manageAddressesPreference.setIcon(R.drawable.ic_new)
|
||||||
|
manageAddressesPreference.title =
|
||||||
|
getString(R.string.preferences_addresses_add_address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates preferences visibility depending on credit cards being already saved or not.
|
* Updates preferences visibility depending on credit cards being already saved or not.
|
||||||
*/
|
*/
|
||||||
@ -185,22 +210,25 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all the credit cards from autofillStorage and updates the [AutofillFragmentState]
|
* Fetches all the addresses and credit cards from [AutofillCreditCardsAddressesStorage] and
|
||||||
* with the list of credit cards.
|
* updates the [AutofillFragmentState].
|
||||||
*/
|
*/
|
||||||
private fun loadCreditCards() {
|
private fun loadAutofillState() {
|
||||||
if (isCreditCardsListLoaded) {
|
if (isAutofillStateLoaded) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val addresses = requireComponents.core.autofillStorage.getAllAddresses()
|
||||||
val creditCards = requireComponents.core.autofillStorage.getAllCreditCards()
|
val creditCards = requireComponents.core.autofillStorage.getAllCreditCards()
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.Main) {
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
store.dispatch(AutofillAction.UpdateAddresses(addresses))
|
||||||
store.dispatch(AutofillAction.UpdateCreditCards(creditCards))
|
store.dispatch(AutofillAction.UpdateCreditCards(creditCards))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isCreditCardsListLoaded = true
|
isAutofillStateLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ class CreditCardsManagementFragment : SecureFragment() {
|
|||||||
val view = inflater.inflate(CreditCardsManagementView.LAYOUT_ID, container, false)
|
val view = inflater.inflate(CreditCardsManagementView.LAYOUT_ID, container, false)
|
||||||
|
|
||||||
store = StoreProvider.get(this) {
|
store = StoreProvider.get(this) {
|
||||||
AutofillFragmentStore(AutofillFragmentState(creditCards = emptyList()))
|
AutofillFragmentStore(AutofillFragmentState())
|
||||||
}
|
}
|
||||||
|
|
||||||
interactor = DefaultCreditCardsManagementInteractor(
|
interactor = DefaultCreditCardsManagementInteractor(
|
||||||
|
@ -1499,6 +1499,8 @@
|
|||||||
<string name="preferences_credit_cards_add_credit_card">Add credit card</string>
|
<string name="preferences_credit_cards_add_credit_card">Add credit card</string>
|
||||||
<!-- Preference option for managing saved credit cards -->
|
<!-- Preference option for managing saved credit cards -->
|
||||||
<string name="preferences_credit_cards_manage_saved_cards">Manage saved cards</string>
|
<string name="preferences_credit_cards_manage_saved_cards">Manage saved cards</string>
|
||||||
|
<!-- Preference option for adding an address -->
|
||||||
|
<string name="preferences_addresses_add_address">Add address</string>
|
||||||
<!-- Preference option for managing saved addresses -->
|
<!-- Preference option for managing saved addresses -->
|
||||||
<string name="preferences_addresses_manage_addresses">Manage addresses</string>
|
<string name="preferences_addresses_manage_addresses">Manage addresses</string>
|
||||||
<!-- Title of the "Add card" screen -->
|
<!-- Title of the "Add card" screen -->
|
||||||
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.settings.autofill
|
|||||||
|
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.concept.storage.CreditCard
|
import mozilla.components.concept.storage.CreditCard
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
@ -20,7 +21,7 @@ class AutofillFragmentStoreTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
state = AutofillFragmentState(creditCards = emptyList())
|
state = AutofillFragmentState()
|
||||||
store = AutofillFragmentStore(state)
|
store = AutofillFragmentStore(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,4 +35,15 @@ class AutofillFragmentStoreTest {
|
|||||||
assertEquals(creditCards, store.state.creditCards)
|
assertEquals(creditCards, store.state.creditCards)
|
||||||
assertFalse(store.state.isLoading)
|
assertFalse(store.state.isLoading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN a list of addresses WHEN update addresses action is dispatched THEN addresses state is updated`() = runBlocking {
|
||||||
|
assertTrue(store.state.isLoading)
|
||||||
|
|
||||||
|
val addresses: List<Address> = listOf(mockk(), mockk())
|
||||||
|
store.dispatch(AutofillAction.UpdateAddresses(addresses)).join()
|
||||||
|
|
||||||
|
assertEquals(addresses, store.state.addresses)
|
||||||
|
assertFalse(store.state.isLoading)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import io.mockk.every
|
|||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.concept.storage.CreditCard
|
import mozilla.components.concept.storage.CreditCard
|
||||||
import mozilla.components.support.test.robolectric.testContext
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
@ -35,6 +36,8 @@ class AutofillSettingFragmentTest {
|
|||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
every { testContext.components.settings } returns mockk(relaxed = true)
|
every { testContext.components.settings } returns mockk(relaxed = true)
|
||||||
|
every { testContext.components.settings.addressFeature } returns true
|
||||||
|
every { testContext.components.settings.shouldAutofillCreditCardDetails } returns true
|
||||||
|
|
||||||
autofillSettingFragment = AutofillSettingFragment()
|
autofillSettingFragment = AutofillSettingFragment()
|
||||||
|
|
||||||
@ -80,7 +83,7 @@ class AutofillSettingFragmentTest {
|
|||||||
AutofillSettingFragmentDirections
|
AutofillSettingFragmentDirections
|
||||||
.actionAutofillSettingFragmentToCreditCardEditorFragment()
|
.actionAutofillSettingFragmentToCreditCardEditorFragment()
|
||||||
|
|
||||||
val state = AutofillFragmentState(creditCards = emptyList())
|
val state = AutofillFragmentState()
|
||||||
val store = AutofillFragmentStore(state)
|
val store = AutofillFragmentStore(state)
|
||||||
|
|
||||||
autofillSettingFragment.updateCardManagementPreference(
|
autofillSettingFragment.updateCardManagementPreference(
|
||||||
@ -95,4 +98,44 @@ class AutofillSettingFragmentTest {
|
|||||||
|
|
||||||
verify { navController.navigate(directions) }
|
verify { navController.navigate(directions) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the list of addresses is not empty WHEN fragment is displayed THEN the manage addresses preference label is 'Manage addresses'`() {
|
||||||
|
val preferenceTitle =
|
||||||
|
testContext.getString(R.string.preferences_addresses_manage_addresses)
|
||||||
|
val manageCardsPreference = autofillSettingFragment.findPreference<Preference>(
|
||||||
|
autofillSettingFragment.getPreferenceKey(R.string.pref_key_addresses_manage_addresses)
|
||||||
|
)
|
||||||
|
|
||||||
|
val addresses: List<Address> = listOf(mockk(), mockk())
|
||||||
|
|
||||||
|
val state = AutofillFragmentState(addresses = addresses)
|
||||||
|
val store = AutofillFragmentStore(state)
|
||||||
|
|
||||||
|
autofillSettingFragment.updateAddressPreference(
|
||||||
|
store.state.addresses.isNotEmpty()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNull(manageCardsPreference?.icon)
|
||||||
|
assertEquals(preferenceTitle, manageCardsPreference?.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the list of addresses is empty WHEN fragment is displayed THEN the manage addresses preference label is 'Add address'`() {
|
||||||
|
val preferenceTitle =
|
||||||
|
testContext.getString(R.string.preferences_addresses_add_address)
|
||||||
|
val manageCardsPreference = autofillSettingFragment.findPreference<Preference>(
|
||||||
|
autofillSettingFragment.getPreferenceKey(R.string.pref_key_addresses_manage_addresses)
|
||||||
|
)
|
||||||
|
|
||||||
|
val state = AutofillFragmentState()
|
||||||
|
val store = AutofillFragmentStore(state)
|
||||||
|
|
||||||
|
autofillSettingFragment.updateAddressPreference(
|
||||||
|
store.state.addresses.isNotEmpty()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNotNull(manageCardsPreference?.icon)
|
||||||
|
assertEquals(preferenceTitle, manageCardsPreference?.title)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class CreditCardsManagementViewTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUpdate() {
|
fun testUpdate() {
|
||||||
creditCardsView.update(AutofillFragmentState(creditCards = emptyList()))
|
creditCardsView.update(AutofillFragmentState())
|
||||||
|
|
||||||
assertTrue(componentCreditCardsBinding.progressBar.isVisible)
|
assertTrue(componentCreditCardsBinding.progressBar.isVisible)
|
||||||
assertFalse(componentCreditCardsBinding.creditCardsList.isVisible)
|
assertFalse(componentCreditCardsBinding.creditCardsList.isVisible)
|
||||||
|
Loading…
Reference in New Issue
Block a user