mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/24855: Allow updating info for an existing address.
This commit is contained in:
parent
81e4534da1
commit
02fb70abf9
@ -8,6 +8,7 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.navigation.fragment.navArgs
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.SecureFragment
|
import org.mozilla.fenix.SecureFragment
|
||||||
@ -27,6 +28,14 @@ class AddressEditorFragment : SecureFragment(R.layout.fragment_address_editor) {
|
|||||||
private lateinit var addressEditorView: AddressEditorView
|
private lateinit var addressEditorView: AddressEditorView
|
||||||
private lateinit var interactor: AddressEditorInteractor
|
private lateinit var interactor: AddressEditorInteractor
|
||||||
|
|
||||||
|
private val args by navArgs<AddressEditorFragmentArgs>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if an existing address is being edited, and false otherwise.
|
||||||
|
*/
|
||||||
|
private val isEditing: Boolean
|
||||||
|
get() = args.address != null
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
@ -42,14 +51,18 @@ class AddressEditorFragment : SecureFragment(R.layout.fragment_address_editor) {
|
|||||||
|
|
||||||
val binding = FragmentAddressEditorBinding.bind(view)
|
val binding = FragmentAddressEditorBinding.bind(view)
|
||||||
|
|
||||||
addressEditorView = AddressEditorView(binding, interactor)
|
addressEditorView = AddressEditorView(binding, interactor, args.address)
|
||||||
addressEditorView.bind()
|
addressEditorView.bind()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
if (isEditing) {
|
||||||
|
showToolbar(getString(R.string.addresses_edit_address))
|
||||||
|
} else {
|
||||||
showToolbar(getString(R.string.addresses_add_address))
|
showToolbar(getString(R.string.addresses_add_address))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
|
@ -28,6 +28,11 @@ interface AddressEditorController {
|
|||||||
* @see [AddressEditorInteractor.onSaveAddress]
|
* @see [AddressEditorInteractor.onSaveAddress]
|
||||||
*/
|
*/
|
||||||
fun handleSaveAddress(addressFields: UpdatableAddressFields)
|
fun handleSaveAddress(addressFields: UpdatableAddressFields)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see [AddressEditorInteractor.onUpdateAddress]
|
||||||
|
*/
|
||||||
|
fun handleUpdateAddress(guid: String, addressFields: UpdatableAddressFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,4 +62,14 @@ class DefaultAddressEditorController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleUpdateAddress(guid: String, addressFields: UpdatableAddressFields) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
storage.updateAddress(guid, addressFields)
|
||||||
|
|
||||||
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,17 +37,19 @@ class DefaultAddressManagementController(
|
|||||||
) : AddressManagementController {
|
) : AddressManagementController {
|
||||||
|
|
||||||
override fun handleAddressClicked(address: Address) {
|
override fun handleAddressClicked(address: Address) {
|
||||||
navigateToAddressEditor()
|
navigateToAddressEditor(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleAddAddressButtonClicked() {
|
override fun handleAddAddressButtonClicked() {
|
||||||
navigateToAddressEditor()
|
navigateToAddressEditor()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToAddressEditor() {
|
private fun navigateToAddressEditor(address: Address? = null) {
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
AddressManagementFragmentDirections
|
AddressManagementFragmentDirections
|
||||||
.actionAddressManagementFragmentToAddressEditorFragment()
|
.actionAddressManagementFragmentToAddressEditorFragment(
|
||||||
|
address = address
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,14 @@ interface AddressEditorInteractor {
|
|||||||
* @param addressFields A [UpdatableAddressFields] record to add.
|
* @param addressFields A [UpdatableAddressFields] record to add.
|
||||||
*/
|
*/
|
||||||
fun onSaveAddress(addressFields: UpdatableAddressFields)
|
fun onSaveAddress(addressFields: UpdatableAddressFields)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the provided address in the autofill storage. Called when a user
|
||||||
|
* taps on the update menu item or "Update" button.
|
||||||
|
*
|
||||||
|
* @param addressFields A [UpdatableAddressFields] record to add.
|
||||||
|
*/
|
||||||
|
fun onUpdateAddress(guid: String, addressFields: UpdatableAddressFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,4 +52,8 @@ class DefaultAddressEditorInteractor(
|
|||||||
override fun onSaveAddress(addressFields: UpdatableAddressFields) {
|
override fun onSaveAddress(addressFields: UpdatableAddressFields) {
|
||||||
controller.handleSaveAddress(addressFields)
|
controller.handleSaveAddress(addressFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onUpdateAddress(guid: String, addressFields: UpdatableAddressFields) {
|
||||||
|
controller.handleUpdateAddress(guid, addressFields)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,15 @@
|
|||||||
|
|
||||||
package org.mozilla.fenix.settings.address.view
|
package org.mozilla.fenix.settings.address.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.concept.storage.UpdatableAddressFields
|
import mozilla.components.concept.storage.UpdatableAddressFields
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
import mozilla.components.support.ktx.android.view.showKeyboard
|
import mozilla.components.support.ktx.android.view.showKeyboard
|
||||||
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.databinding.FragmentAddressEditorBinding
|
import org.mozilla.fenix.databinding.FragmentAddressEditorBinding
|
||||||
import org.mozilla.fenix.ext.placeCursorAtEnd
|
import org.mozilla.fenix.ext.placeCursorAtEnd
|
||||||
import org.mozilla.fenix.settings.address.interactor.AddressEditorInteractor
|
import org.mozilla.fenix.settings.address.interactor.AddressEditorInteractor
|
||||||
@ -16,7 +22,8 @@ import org.mozilla.fenix.settings.address.interactor.AddressEditorInteractor
|
|||||||
*/
|
*/
|
||||||
class AddressEditorView(
|
class AddressEditorView(
|
||||||
private val binding: FragmentAddressEditorBinding,
|
private val binding: FragmentAddressEditorBinding,
|
||||||
private val interactor: AddressEditorInteractor
|
private val interactor: AddressEditorInteractor,
|
||||||
|
private val address: Address? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,13 +43,26 @@ class AddressEditorView(
|
|||||||
binding.saveButton.setOnClickListener {
|
binding.saveButton.setOnClickListener {
|
||||||
saveAddress()
|
saveAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address?.let { address ->
|
||||||
|
binding.emailInput.setText(address.email)
|
||||||
|
binding.phoneInput.setText(address.tel)
|
||||||
|
|
||||||
|
binding.firstNameInput.setText(address.givenName)
|
||||||
|
binding.middleNameInput.setText(address.additionalName)
|
||||||
|
binding.lastNameInput.setText(address.familyName)
|
||||||
|
|
||||||
|
binding.streetAddressInput.setText(address.streetAddress)
|
||||||
|
binding.cityInput.setText(address.addressLevel2)
|
||||||
|
binding.stateInput.setText(address.addressLevel1)
|
||||||
|
binding.zipInput.setText(address.postalCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun saveAddress() {
|
internal fun saveAddress() {
|
||||||
binding.root.hideKeyboard()
|
binding.root.hideKeyboard()
|
||||||
|
|
||||||
interactor.onSaveAddress(
|
val addressFields = UpdatableAddressFields(
|
||||||
UpdatableAddressFields(
|
|
||||||
givenName = binding.firstNameInput.text.toString(),
|
givenName = binding.firstNameInput.text.toString(),
|
||||||
additionalName = binding.middleNameInput.text.toString(),
|
additionalName = binding.middleNameInput.text.toString(),
|
||||||
familyName = binding.lastNameInput.text.toString(),
|
familyName = binding.lastNameInput.text.toString(),
|
||||||
@ -56,6 +76,11 @@ class AddressEditorView(
|
|||||||
tel = binding.phoneInput.text.toString(),
|
tel = binding.phoneInput.text.toString(),
|
||||||
email = binding.emailInput.text.toString()
|
email = binding.emailInput.text.toString()
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
if (address != null) {
|
||||||
|
interactor.onUpdateAddress(address.guid, addressFields)
|
||||||
|
} else {
|
||||||
|
interactor.onSaveAddress(addressFields)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1258,7 +1258,13 @@
|
|||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/addressEditorFragment"
|
android:id="@+id/addressEditorFragment"
|
||||||
android:name="org.mozilla.fenix.settings.address.AddressEditorFragment"
|
android:name="org.mozilla.fenix.settings.address.AddressEditorFragment"
|
||||||
android:label="@string/addresses_add_address" />
|
android:label="@string/addresses_add_address">
|
||||||
|
<argument
|
||||||
|
android:name="address"
|
||||||
|
android:defaultValue="@null"
|
||||||
|
app:argType="mozilla.components.concept.storage.Address"
|
||||||
|
app:nullable="true" />
|
||||||
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/addressManagementFragment"
|
android:id="@+id/addressManagementFragment"
|
||||||
android:name="org.mozilla.fenix.settings.address.AddressManagementFragment"
|
android:name="org.mozilla.fenix.settings.address.AddressManagementFragment"
|
||||||
|
@ -1546,6 +1546,8 @@
|
|||||||
<string name="credit_cards_biometric_prompt_unlock_message">Unlock to use stored credit card information</string>
|
<string name="credit_cards_biometric_prompt_unlock_message">Unlock to use stored credit card information</string>
|
||||||
<!-- Title of the "Add address" screen -->
|
<!-- Title of the "Add address" screen -->
|
||||||
<string name="addresses_add_address">Add address</string>
|
<string name="addresses_add_address">Add address</string>
|
||||||
|
<!-- Title of the "Edit address" screen -->
|
||||||
|
<string name="addresses_edit_address">Edit address</string>
|
||||||
<!-- Title of the "Manage addresses" screen -->
|
<!-- Title of the "Manage addresses" screen -->
|
||||||
<string name="addresses_manage_addresses">Manage addresses</string>
|
<string name="addresses_manage_addresses">Manage addresses</string>
|
||||||
<!-- The header for the full name of an address -->
|
<!-- The header for the full name of an address -->
|
||||||
|
@ -6,10 +6,13 @@ package org.mozilla.fenix.settings.address
|
|||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.spyk
|
import io.mockk.spyk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.support.test.robolectric.testContext
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@ -26,12 +29,15 @@ class AddressEditorViewTest {
|
|||||||
private lateinit var interactor: AddressEditorInteractor
|
private lateinit var interactor: AddressEditorInteractor
|
||||||
private lateinit var addressEditorView: AddressEditorView
|
private lateinit var addressEditorView: AddressEditorView
|
||||||
private lateinit var binding: FragmentAddressEditorBinding
|
private lateinit var binding: FragmentAddressEditorBinding
|
||||||
|
private lateinit var address: Address
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
view = LayoutInflater.from(testContext).inflate(R.layout.fragment_address_editor, null)
|
view = LayoutInflater.from(testContext).inflate(R.layout.fragment_address_editor, null)
|
||||||
binding = FragmentAddressEditorBinding.bind(view)
|
binding = FragmentAddressEditorBinding.bind(view)
|
||||||
interactor = mockk(relaxed = true)
|
interactor = mockk(relaxed = true)
|
||||||
|
address = mockk(relaxed = true)
|
||||||
|
every { address.guid } returns "123"
|
||||||
|
|
||||||
addressEditorView = spyk(AddressEditorView(binding, interactor))
|
addressEditorView = spyk(AddressEditorView(binding, interactor))
|
||||||
}
|
}
|
||||||
@ -44,4 +50,40 @@ class AddressEditorViewTest {
|
|||||||
|
|
||||||
verify { interactor.onCancelButtonClicked() }
|
verify { interactor.onCancelButtonClicked() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN an existing address WHEN editor is opened THEN the form fields are correctly mapped to the address fields`() {
|
||||||
|
val address = Address(
|
||||||
|
guid = "123",
|
||||||
|
givenName = "Given",
|
||||||
|
additionalName = "Additional",
|
||||||
|
familyName = "Family",
|
||||||
|
organization = "Organization",
|
||||||
|
streetAddress = "Street",
|
||||||
|
addressLevel3 = "Suburb",
|
||||||
|
addressLevel2 = "City",
|
||||||
|
addressLevel1 = "State",
|
||||||
|
postalCode = "PostalCode",
|
||||||
|
country = "Country",
|
||||||
|
tel = "Telephone",
|
||||||
|
email = "email@mozilla.com",
|
||||||
|
timeCreated = 0L,
|
||||||
|
timeLastUsed = 1L,
|
||||||
|
timeLastModified = 1L,
|
||||||
|
timesUsed = 2L
|
||||||
|
)
|
||||||
|
|
||||||
|
val addressEditorView = spyk(AddressEditorView(binding, interactor, address))
|
||||||
|
addressEditorView.bind()
|
||||||
|
|
||||||
|
assertEquals("PostalCode", binding.zipInput.text.toString())
|
||||||
|
assertEquals("State", binding.stateInput.text.toString())
|
||||||
|
assertEquals("City", binding.cityInput.text.toString())
|
||||||
|
assertEquals("Street", binding.streetAddressInput.text.toString())
|
||||||
|
assertEquals("Family", binding.lastNameInput.text.toString())
|
||||||
|
assertEquals("Given", binding.firstNameInput.text.toString())
|
||||||
|
assertEquals("Additional", binding.middleNameInput.text.toString())
|
||||||
|
assertEquals("email@mozilla.com", binding.emailInput.text.toString())
|
||||||
|
assertEquals("Telephone", binding.phoneInput.text.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,14 @@ package org.mozilla.fenix.settings.address.controller
|
|||||||
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import io.mockk.coVerify
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.coVerifySequence
|
||||||
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.spyk
|
import io.mockk.spyk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.test.TestCoroutineScope
|
import kotlinx.coroutines.test.TestCoroutineScope
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
|
import mozilla.components.concept.storage.Address
|
||||||
import mozilla.components.concept.storage.UpdatableAddressFields
|
import mozilla.components.concept.storage.UpdatableAddressFields
|
||||||
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
|
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
|
||||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||||
@ -73,4 +76,18 @@ class DefaultAddressEditorControllerTest {
|
|||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN an existing address record WHEN save address is called THEN update the address record to storage`() = runBlockingTest {
|
||||||
|
val address: Address = mockk()
|
||||||
|
val addressFields: UpdatableAddressFields = mockk()
|
||||||
|
every { address.guid } returns "123"
|
||||||
|
|
||||||
|
controller.handleUpdateAddress(address.guid, addressFields)
|
||||||
|
|
||||||
|
coVerifySequence {
|
||||||
|
storage.updateAddress("123", addressFields)
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@ class DefaultAddressManagementControllerTest {
|
|||||||
verify {
|
verify {
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
AddressManagementFragmentDirections
|
AddressManagementFragmentDirections
|
||||||
.actionAddressManagementFragmentToAddressEditorFragment()
|
.actionAddressManagementFragmentToAddressEditorFragment(
|
||||||
|
address = address
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user