diff --git a/build.gradle b/build.gradle index c8bea05e8..7d443fbbc 100644 --- a/build.gradle +++ b/build.gradle @@ -23,8 +23,7 @@ allprojects { mavenLocal() } - - project.version = "1.0.0-beta03-SNAPSHOT"; + project.version = "1.0.0-beta03-SNAPSHOT" } task clean(type: Delete) { diff --git a/ui/build.gradle b/ui/build.gradle index 36be7e3cb..36e57ea3a 100644 --- a/ui/build.gradle +++ b/ui/build.gradle @@ -49,7 +49,7 @@ dependencies { implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.recyclerview:recyclerview:1.0.0" - api 'com.hyperwallet.android:core-sdk:1.0.0-beta02' + api "com.hyperwallet.android:core-sdk:1.0.0-beta03-SNAPSHOT" androidTestImplementation "androidx.test.ext:junit:1.1.0" androidTestImplementation "androidx.test:runner:1.1.1" @@ -61,7 +61,7 @@ dependencies { androidTestImplementation "com.squareup.leakcanary:leakcanary-android-instrumentation:1.6.3" androidTestImplementation "com.squareup.leakcanary:leakcanary-support-fragment:1.6.3" - testImplementation group: 'org.mockito', name: 'mockito-core', version: "2.23.4" + testImplementation group: 'org.mockito', name: 'mockito-core', version: "2.25.0" testImplementation group: 'pl.pragmatists', name: 'JUnitParams', version: "1.1.1" testImplementation "org.robolectric:robolectric:4.1" testImplementation "com.squareup.okhttp3:mockwebserver:3.11.0" diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java index 914cfde4a..c4af970ff 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java @@ -124,7 +124,7 @@ public void testAddTransferMethod_accountDetailsHiddenOnEmptyFeeAndProcessingRes @Test public void testAddTransferMethod_displaysErrorDialogOnDuplicateAccountFailure() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_BAD_REQUEST).withBody(sResourceManager .getResourceContent("bank_account_duplicate_routing_response.json")).mock(); @@ -159,7 +159,7 @@ public void testAddTransferMethod_displaysErrorDialogOnDuplicateAccountFailure() @Test public void testAddTransferMethod_displaysUnexpectedErrorDialogOnException() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_BAD_REQUEST).withBody(sResourceManager .getResourceContent("invalid_json_response.json")).mock(); @@ -189,7 +189,7 @@ public void testAddTransferMethod_displaysUnexpectedErrorDialogOnException() { @Test public void testAddTransferMethod_displaysNetworkErrorDialogOnConnectionTimeout() throws IOException { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mActivityTestRule.launchActivity(null); diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java index 3a48ac15e..9134735a2 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java @@ -7,7 +7,9 @@ import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -16,6 +18,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_CREATED; @@ -23,6 +26,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static com.hyperwallet.android.model.HyperwalletBankAccount.Purpose.SAVINGS; +import static com.hyperwallet.android.util.EspressoUtils.hasEmptyText; import static com.hyperwallet.android.util.EspressoUtils.hasErrorText; import static com.hyperwallet.android.util.EspressoUtils.nestedScrollTo; import static com.hyperwallet.android.util.EspressoUtils.withHint; @@ -37,6 +41,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.espresso.IdlingRegistry; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; @@ -63,9 +68,6 @@ @RunWith(AndroidJUnit4.class) public class BankAccountTest { - private static final String ACCOUNT_NUMBER_LABEL = "Account Number"; - private static final String ROUTING_NUMBER_LABEL = "Routing Number"; - private static final String ACCOUNT_TYPE_LABEL = "Account Type"; private static final String ACCOUNT_NUMBER = "8017110254"; private static final String ROUTING_NUMBER = "211179539"; private static final String INVALID_ROUTING_NUMBER = "211179531"; @@ -96,7 +98,7 @@ public void setup() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("authentication_token_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); } @After @@ -118,31 +120,133 @@ public void unregisterIdlingResource() { public void testAddTransferMethod_displaysElementsOnTmcResponse() { mActivityTestRule.launchActivity(null); - onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))).check( - matches(withText(R.string.title_add_bank_account))); - - onView(withId(R.id.branchId)).check(matches(isDisplayed())); - onView(withId(R.id.branchIdLabel)).check(matches(withHint(ROUTING_NUMBER_LABEL))); - onView(withId(R.id.bankAccountId)).check(matches(isDisplayed())); - onView(withId(R.id.bankAccountIdLabel)).check(matches(withHint(ACCOUNT_NUMBER_LABEL))); - onView(withId(R.id.bankAccountPurpose)).check(matches(isDisplayed())); + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_add_bank_account))); + + onView(allOf(withId(R.id.section_header_title), withText("Account Information - United States (USD)"))).check( + matches(isDisplayed())); + onView(withId(R.id.branchId)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.branchIdLabel)).check(matches(isDisplayed())); + onView(withId(R.id.branchIdLabel)).check(matches(withHint("Routing Number"))); + onView(withId(R.id.bankAccountId)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.bankAccountIdLabel)).check(matches(isDisplayed())); + onView(withId(R.id.bankAccountIdLabel)).check(matches(withHint("Account Number"))); + onView(withId(R.id.bankAccountPurpose)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.bankAccountPurposeLabel)).check(matches(isDisplayed())); onView(withId(R.id.bankAccountPurposeLabel)).check( - matches(withHint(ACCOUNT_TYPE_LABEL))); - - onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo()).check( - matches(withText(R.string.button_create_transfer_method))); + matches(withHint("Account Type"))); + + onView(allOf(withId(R.id.section_header_title), withText("Account Holder"))).perform(nestedScrollTo()).check( + matches(isDisplayed())); + onView(withId(R.id.firstName)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.firstNameLabel)).check(matches(isDisplayed())); + onView(withId(R.id.firstNameLabel)).check(matches(withHint("First Name"))); + onView(withId(R.id.middleName)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.middleNameLabel)).check(matches(isDisplayed())); + onView(withId(R.id.middleNameLabel)).check(matches(withHint("Middle Name"))); + onView(withId(R.id.lastName)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.lastNameLabel)).check(matches(isDisplayed())); + onView(withId(R.id.lastNameLabel)).check(matches(withHint("Last Name"))); + onView(withId(R.id.dateOfBirth)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.dateOfBirthLabel)).check(matches(isDisplayed())); + onView(withId(R.id.dateOfBirthLabel)).check(matches(withHint("Date of Birth"))); + + onView(allOf(withId(R.id.section_header_title), withText("Contact Information"))).perform( + nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.phoneNumber)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.phoneNumberLabel)).check(matches(isDisplayed())); + onView(withId(R.id.phoneNumberLabel)).check(matches(withHint("Phone Number"))); + onView(withId(R.id.mobileNumber)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.mobileNumberLabel)).check(matches(isDisplayed())); + onView(withId(R.id.mobileNumberLabel)).check(matches(withHint("Mobile Number"))); + + onView(allOf(withId(R.id.section_header_title), withText("Address"))).perform(nestedScrollTo()).check( + matches(isDisplayed())); + onView(withId(R.id.country)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.countryLabel)).check(matches(isDisplayed())); + onView(withId(R.id.countryLabel)).check(matches(withHint("Country"))); + onView(withId(R.id.stateProvince)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.stateProvinceLabel)).check(matches(isDisplayed())); + onView(withId(R.id.stateProvinceLabel)).check(matches(withHint("State/Province"))); + onView(withId(R.id.addressLine1)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.addressLine1Label)).check(matches(isDisplayed())); + onView(withId(R.id.addressLine1Label)).check(matches(withHint("Street"))); + onView(withId(R.id.city)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.cityLabel)).check(matches(isDisplayed())); + onView(withId(R.id.cityLabel)).check(matches(withHint("City"))); + onView(withId(R.id.postalCode)).perform(nestedScrollTo()).check(matches(isDisplayed())); + onView(withId(R.id.postalCodeLabel)).check(matches(isDisplayed())); + onView(withId(R.id.postalCodeLabel)).check(matches(withHint("Zip/Postal Code"))); + + onView(withId(R.id.add_transfer_method_button)) + .perform(nestedScrollTo()).check(matches(withText(R.string.button_create_transfer_method))); } @Test public void testAddTransferMethod_displaysFeeElementsOnTmcResponse() { mActivityTestRule.launchActivity(null); + onView(withId(R.id.add_transfer_method_static_container)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); + + onView(withId(R.id.add_transfer_method_fee_label)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); onView(withId(R.id.add_transfer_method_fee_label)).check( matches(withText(R.string.add_transfer_method_fee_label))); - onView(withId(R.id.add_transfer_method_processing_label)).check( - matches(withText(R.string.add_transfer_method_processing_time_label))); onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("USD 2.00"))); - onView(withId(R.id.add_transfer_method_processing_time_value)).check(matches(withText("1-2 Business days"))); + + //TODO: Uncomment when processing time node is implemented +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withText(R.string.add_transfer_method_processing_time_label))); +// onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("1 - 2 Business Days"))); + } + + @Test + public void testAddTransferMethod_verifyDefaultValues() { + mActivityTestRule.launchActivity(null); + + onView(withId(R.id.branchId)).check(matches(hasEmptyText())); + onView(withId(R.id.bankAccountId)).check(matches(hasEmptyText())); + onView(withId(R.id.bankAccountPurpose)).check(matches(hasEmptyText())); + + onView(withId(R.id.firstName)).check(matches(withText("Brody"))); + onView(withId(R.id.middleName)).check(matches(hasEmptyText())); + onView(withId(R.id.lastName)).check(matches(withText("Nehru"))); + onView(withId(R.id.dateOfBirth)).check(matches(withText("2000-01-01"))); + + onView(withId(R.id.phoneNumber)).check(matches(withText("+1 604 6666666"))); + onView(withId(R.id.mobileNumber)).check(matches(withText("604 666 6666"))); + + onView(withId(R.id.country)).check(matches(withText("Canada"))); + onView(withId(R.id.stateProvince)).check(matches(withText("BC"))); + onView(withId(R.id.addressLine1)).check(matches(withText("950 Granville Street"))); + onView(withId(R.id.city)).check(matches(withText("Vancouver"))); + onView(withId(R.id.postalCode)).check(matches(withText("V6Z1L2"))); + } + + @Test + public void testAddTransferMethod_verifyEditableFields() { + mActivityTestRule.launchActivity(null); + + onView(withId(R.id.branchId)).check(matches(isEnabled())); + onView(withId(R.id.bankAccountId)).check(matches(isEnabled())); + onView(withId(R.id.bankAccountPurpose)).check(matches(isEnabled())); + + onView(withId(R.id.firstName)).check(matches(not(isEnabled()))); + onView(withId(R.id.middleName)).check(matches(isEnabled())); + onView(withId(R.id.lastName)).check(matches(isEnabled())); + onView(withId(R.id.dateOfBirth)).check(matches(isEnabled())); + + onView(withId(R.id.phoneNumber)).check(matches(isEnabled())); + onView(withId(R.id.mobileNumber)).check(matches(isEnabled())); + + onView(withId(R.id.country)).check(matches(not(isEnabled()))); + onView(withId(R.id.stateProvince)).check(matches(isEnabled())); + onView(withId(R.id.addressLine1)).check(matches(isEnabled())); + onView(withId(R.id.city)).check(matches(isEnabled())); + onView(withId(R.id.postalCode)).check(matches(isEnabled())); } @Test @@ -166,6 +270,28 @@ public void onReceive(Context context, Intent intent) { HyperwalletTransferMethod.TransferMethodFields.BRANCH_ID), is(ROUTING_NUMBER)); assertThat("Bank Account purpose is incorrect", transferMethod.getField( HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_PURPOSE), is(SAVINGS)); + + assertThat("First Name is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.FIRST_NAME), is("Brody")); + assertThat("Last Name is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.LAST_NAME), is("Nehru")); + assertThat("Date of birth is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.DATE_OF_BIRTH), is("2000-01-01")); + + assertThat("Phone Number is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.PHONE_NUMBER), is("+1 604 6666666")); + assertThat("Mobile Number incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.MOBILE_NUMBER), is("604 666 6666")); + assertThat("Country is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.COUNTRY), is("CA")); + assertThat("State Province is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.STATE_PROVINCE), is("BC")); + assertThat("Address is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.ADDRESS_LINE_1), is("950 Granville Street")); + assertThat("City is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.CITY), is("Vancouver")); + assertThat("Postal Code is incorrect", transferMethod.getField( + HyperwalletTransferMethod.TransferMethodFields.POSTAL_CODE), is("V6Z1L2")); } }; @@ -173,11 +299,9 @@ public void onReceive(Context context, Intent intent) { .registerReceiver(br, new IntentFilter("ACTION_HYPERWALLET_TRANSFER_METHOD_ADDED")); onView(withId(R.id.branchId)) - .perform(typeText(ROUTING_NUMBER)) - .perform(closeSoftKeyboard()); + .perform(typeText(ROUTING_NUMBER)).perform(closeSoftKeyboard()); onView(withId(R.id.bankAccountId)) - .perform(typeText(ACCOUNT_NUMBER)) - .perform(closeSoftKeyboard()); + .perform(typeText(ACCOUNT_NUMBER)).perform(closeSoftKeyboard()); onView(withId(R.id.bankAccountPurpose)).perform(click()); onView(withId(R.id.search_button)).check(doesNotExist()); onView(withId(R.id.input_selection_list)).check(new RecyclerViewCountAssertion(2)); @@ -211,17 +335,16 @@ public void testAddTransferMethod_returnsErrorOnInvalidPresence() { onView(withId(R.id.bankAccountPurpose)).perform(click()); onView(allOf(withContentDescription(R.string.abc_action_bar_up_description), - withParent(withId(R.id.input_selection_toolbar)))).perform( - click()); + withParent(withId(R.id.input_selection_toolbar)))).perform(click()); onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo(), click()); onView(withId(R.id.branchIdLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); onView(withId(R.id.bankAccountIdLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); onView(withId(R.id.bankAccountPurposeLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); } @Test @@ -229,11 +352,9 @@ public void testAddTransferMethod_returnsErrorOnInvalidLength() { mActivityTestRule.launchActivity(null); onView(withId(R.id.branchId)) - .perform(typeText("2111795311")) - .perform(closeSoftKeyboard()); + .perform(typeText("2111795311")).perform(closeSoftKeyboard()); onView(withId(R.id.bankAccountId)) - .perform(typeText("1")) - .perform(closeSoftKeyboard()); + .perform(typeText("1")).perform(closeSoftKeyboard()); onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo(), click()); diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java index 8f05f330d..e2d2c1003 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java @@ -7,6 +7,7 @@ import static androidx.test.espresso.action.ViewActions.typeText; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -35,6 +36,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.espresso.IdlingRegistry; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; @@ -98,7 +100,7 @@ public void setup() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("authentication_token_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_bank_card_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_card_response.json")).mock(); } @After @@ -124,12 +126,14 @@ public void testAddTransferMethod_displaysElementsOnTmcResponse() { matches(withText(R.string.title_add_bank_card))); onView(withId(R.id.cardNumber)).check(matches(isDisplayed())); + onView(withId(R.id.cardNumberLabel)).check(matches(isDisplayed())); onView(withId(R.id.cardNumberLabel)).check(matches(withHint(CARD_NUMBER_LABEL))); onView(withId(R.id.dateOfExpiry)).check(matches(isDisplayed())); + onView(withId(R.id.dateOfExpiryLabel)).check(matches(isDisplayed())); onView(withId(R.id.dateOfExpiryLabel)).check(matches(withHint(EXPIRY_DATE_LABEL))); onView(withId(R.id.cvv)).check(matches(isDisplayed())); - onView(withId(R.id.cvvLabel)).check( - matches(withHint(CVV_LABEL))); + onView(withId(R.id.cvvLabel)).check(matches(isDisplayed())); + onView(withId(R.id.cvvLabel)).check(matches(withHint(CVV_LABEL))); onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo()).check( matches(withText(R.string.button_create_transfer_method))); @@ -139,11 +143,21 @@ public void testAddTransferMethod_displaysElementsOnTmcResponse() { public void testAddTransferMethod_displaysFeeElementsOnTmcResponse() { mActivityTestRule.launchActivity(null); + onView(withId(R.id.add_transfer_method_static_container)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); + + onView(withId(R.id.add_transfer_method_fee_label)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); onView(withId(R.id.add_transfer_method_fee_label)).check( matches(withText(R.string.add_transfer_method_fee_label))); - onView(withId(R.id.add_transfer_method_processing_label)).check( - matches(withText(R.string.add_transfer_method_processing_time_label))); onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("USD 1.75"))); + + //TODO: Uncomment when processing time node is implemented +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withText(R.string.add_transfer_method_processing_time_label))); +// onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("1 - 2 Business Days"))); } @Test @@ -211,11 +225,11 @@ public void testAddTransferMethod_returnsErrorOnInvalidPresence() { onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo(), click()); onView(withId(R.id.cardNumberLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); onView(withId(R.id.dateOfExpiryLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); onView(withId(R.id.cvvLabel)) - .check(matches(hasErrorText("You must provide a value for this field."))); + .check(matches(hasErrorText("You must provide a value for this field"))); } @Test diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java index 6bf0ec8bd..0133e6a90 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java @@ -8,6 +8,7 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.RootMatchers.isDialog; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -37,6 +38,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.espresso.IdlingRegistry; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; @@ -88,7 +90,7 @@ public void setup() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("authentication_token_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_paypal_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_paypal_response.json")).mock(); } @After @@ -114,6 +116,7 @@ public void testAddTransferMethod_displaysElementsOnTmcResponse() { matches(withText(R.string.paypal_account))); onView(withId(R.id.email)).check(matches(isDisplayed())); + onView(withId(R.id.emailLabel)).check(matches(isDisplayed())); onView(withId(R.id.emailLabel)).check(matches(withHint("Email"))); onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo()).check( @@ -124,12 +127,22 @@ public void testAddTransferMethod_displaysElementsOnTmcResponse() { public void testAddTransferMethod_displaysFeeElementsOnTmcResponse() { mActivityTestRule.launchActivity(null); + onView(withId(R.id.add_transfer_method_static_container)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); + + onView(withId(R.id.add_transfer_method_fee_label)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); onView(withId(R.id.add_transfer_method_fee_label)).check( matches(withText(R.string.add_transfer_method_fee_label))); - onView(withId(R.id.add_transfer_method_processing_label)).check( - matches(withText(R.string.add_transfer_method_processing_time_label))); onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("USD 0.25"))); - onView(withId(R.id.add_transfer_method_processing_time_value)).check(matches(withText("IMMEDIATE"))); + + //TODO: Uncomment when processing time node is implemented +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); +// onView(withId(R.id.add_transfer_method_processing_label)).check( +// matches(withText(R.string.add_transfer_method_processing_time_label))); +// onView(withId(R.id.add_transfer_method_fee_value)).check(matches(withText("IMMEDIATE"))); + } @Test @@ -178,7 +191,7 @@ public void testAddTransferMethod_returnsErrorOnInvalidPattern() { onView(withId(R.id.add_transfer_method_button)).perform(nestedScrollTo(), click()); onView(withId(R.id.emailLabel)) - .check(matches(hasErrorText("accountNumber is invalid"))); + .check(matches(hasErrorText("is invalid length or format."))); } @Test diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java index 018556a36..01aa039f7 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java @@ -136,9 +136,13 @@ public void testSelectTransferMethod_verifyCountrySelectionList() { onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.country_selection_toolbar)))).check( matches(withText(R.string.select_transfer_method_country))); onView(withId(R.id.search_button)).check(doesNotExist()); - onView(withId(R.id.country_selection_list)).check(new RecyclerViewCountAssertion(2)); + onView(withId(R.id.country_selection_list)).check(new RecyclerViewCountAssertion(5)); onView(allOf(withId(R.id.country_name), withText("Canada"))).check(matches(isDisplayed())); + onView(allOf(withId(R.id.country_name), withText("Croatia"))).check(matches(isDisplayed())); + onView(allOf(withId(R.id.country_name), withText("Mexico"))).check(matches(isDisplayed())); + onView(allOf(withId(R.id.country_name), withText("United Kingdom"))).check(matches(isDisplayed())); onView(allOf(withId(R.id.country_name), withText("United States"))).check(matches(isDisplayed())); + onView(allOf(withId(R.id.country_item_selected_image), hasSibling(allOf(withId(R.id.country_name), withText("United States"))))).check(matches(isDisplayed())); @@ -185,11 +189,12 @@ public void testSelectTransferMethod_verifyCurrencySelectionList() { matches(withText(R.string.select_transfer_method_currency))); onView(withId(R.id.search_button)).check(doesNotExist()); onView(withId(R.id.currency_selection_list)).check(new RecyclerViewCountAssertion(1)); - onView(allOf(withId(R.id.currency_name), withText("US Dollar"))).check(matches(isDisplayed())); + onView(allOf(withId(R.id.currency_name), withText("United States Dollar"))).check(matches(isDisplayed())); onView(allOf(withId(R.id.currency_item_selected_image), - hasSibling(allOf(withId(R.id.currency_name), withText("US Dollar"))))).check(matches(isDisplayed())); + hasSibling(allOf(withId(R.id.currency_name), withText("United States Dollar"))))).check( + matches(isDisplayed())); - onView(allOf(withId(R.id.currency_name), withText("US Dollar"))).perform(click()); + onView(allOf(withId(R.id.currency_name), withText("United States Dollar"))).perform(click()); onView(withId(R.id.select_transfer_method_currency_value)).check(matches(withText("USD"))); } @@ -204,7 +209,7 @@ public void testSelectTransferMethod_verifyTransferMethodsList() { onView(withId(R.id.select_transfer_method_country_value)).check(matches(withText("United States"))); onView(withId(R.id.select_transfer_method_currency_value)).check(matches(withText("USD"))); - onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(2)); + onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(4)); onView(withId(R.id.select_transfer_method_types_list)).check( matches(atPosition(0, hasDescendant(withText(R.string.bank_account_font_icon))))); @@ -222,6 +227,24 @@ public void testSelectTransferMethod_verifyTransferMethodsList() { onView(withId(R.id.select_transfer_method_types_list)).check( matches(atPosition(1, hasDescendant(withText("Transaction Fee: USD 1.75"))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(2, hasDescendant(withText(R.string.wire_account_font_icon))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(2, hasDescendant(withText(R.string.wire_account))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(2, hasDescendant(withText("Transaction Fee: USD 20.00"))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(2, hasDescendant(withText("Processing Time: 1-3 Business days"))))); + + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(3, hasDescendant(withText(R.string.paypal_account_font_icon))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(3, hasDescendant(withText(R.string.paypal_account))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(3, hasDescendant(withText("Transaction Fee: USD 0.25"))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(3, hasDescendant(withText("Processing Time: IMMEDIATE"))))); + } @Test @@ -283,20 +306,29 @@ public void testSelectTransferMethod_verifyTransferMethodsListUpdatedOnSelection onView(withId(R.id.select_transfer_method_country_value)).check(matches(withText("United States"))); onView(withId(R.id.select_transfer_method_currency_value)).check(matches(withText("USD"))); - onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(2)); + onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(4)); onView(withId(R.id.select_transfer_method_country_value)).perform(click()); onView(allOf(withId(R.id.country_name), withText("Canada"))).perform(click()); - onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(1)); + onView(withId(R.id.select_transfer_method_types_list)).check(new RecyclerViewCountAssertion(2)); onView(withId(R.id.select_transfer_method_types_list)).check( matches(atPosition(0, hasDescendant(withText(R.string.bank_account_font_icon))))); onView(withId(R.id.select_transfer_method_types_list)).check( matches(atPosition(0, hasDescendant(withText(R.string.bank_account))))); onView(withId(R.id.select_transfer_method_types_list)).check( - matches(atPosition(0, hasDescendant(withText("Transaction Fee: USD 2.00"))))); + matches(atPosition(0, hasDescendant(withText("Transaction Fee: CAD 2.20"))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(0, hasDescendant(withText("Processing Time: 1-2 Business days"))))); + + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(1, hasDescendant(withText(R.string.paypal_account_font_icon))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(1, hasDescendant(withText(R.string.paypal_account))))); + onView(withId(R.id.select_transfer_method_types_list)).check( + matches(atPosition(1, hasDescendant(withText("Transaction Fee: CAD 0.25"))))); onView(withId(R.id.select_transfer_method_types_list)).check( - matches(atPosition(0, hasDescendant(withText("Processing Time: 1-3 Business days"))))); + matches(atPosition(1, hasDescendant(withText("Processing Time: IMMEDIATE"))))); } @@ -307,7 +339,7 @@ public void testSelectTransferMethod_verifyIntentIndividualUser() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("successful_tmc_keys_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mIntentsTestRule.launchActivity(null); @@ -326,7 +358,7 @@ public void testSelectTransferMethod_verifyIntentBusinessUser() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("successful_tmc_keys_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mIntentsTestRule.launchActivity(null); @@ -345,7 +377,7 @@ public void testSelectTransferMethod_clickBankAccountOpensAddTransferMethodUi() mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("successful_tmc_keys_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_account_response.json")).mock(); mActivityTestRule.launchActivity(null); @@ -362,7 +394,7 @@ public void testSelectTransferMethod_clickBankCardOpensAddTransferMethodUi() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("successful_tmc_keys_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("successful_tmc_bank_card_fields_response.json")).mock(); + .getResourceContent("successful_tmc_fields_bank_card_response.json")).mock(); mActivityTestRule.launchActivity(null); diff --git a/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java b/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java index e7ccb6747..28fb0b590 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.view.View; +import android.widget.EditText; import android.widget.ImageView; import androidx.annotation.NonNull; @@ -131,6 +132,25 @@ public void describeTo(Description description) { }; } + public static Matcher hasEmptyText() { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof EditText)) { + return false; + } + String text = ((EditText) view).getText().toString(); + + return text.isEmpty(); + } + + @Override + public void describeTo(Description description) { + } + }; + } + public static ViewAction nestedScrollTo() { return ViewActions.actionWithAssertions(new NestedScrollToAction()); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepository.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepository.java index bea52cb18..a937b371e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepository.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepository.java @@ -24,15 +24,14 @@ * USE OR OTHER DEALINGS * IN THE SOFTWARE. */ - package com.hyperwallet.android.ui.repository; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.hyperwallet.android.model.HyperwalletErrors; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationFieldResult; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKeyResult; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationField; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKey; public interface TransferMethodConfigurationRepository { @@ -47,15 +46,16 @@ void getFields(@NonNull final String country, @NonNull final String currency, void refreshFields(); interface LoadKeysCallback { - void onKeysLoaded( - @Nullable final HyperwalletTransferMethodConfigurationKeyResult transferMethodConfigurationKeyResult); + + void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKey transferMethodConfigurationKey); void onError(@NonNull final HyperwalletErrors errors); } interface LoadFieldsCallback { - void onFieldsLoaded(@Nullable final HyperwalletTransferMethodConfigurationFieldResult - transferMethodConfigurationFieldResult); + + void onFieldsLoaded(@Nullable final HyperwalletTransferMethodConfigurationField field, + @Nullable final String processingTime); void onError(@NonNull final HyperwalletErrors errors); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java index 89aa23f59..67f2c2278 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java @@ -24,7 +24,6 @@ * USE OR OTHER DEALINGS * IN THE SOFTWARE. */ - package com.hyperwallet.android.ui.repository; import android.os.Handler; @@ -36,8 +35,9 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.exception.HyperwalletException; import com.hyperwallet.android.listener.HyperwalletListener; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationFieldResult; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKeyResult; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationField; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKey; +import com.hyperwallet.android.model.meta.keyed.HyperwalletTransferMethodType; import com.hyperwallet.android.model.meta.query.HyperwalletTransferMethodConfigurationFieldQuery; import com.hyperwallet.android.model.meta.query.HyperwalletTransferMethodConfigurationKeysQuery; import com.hyperwallet.android.ui.util.EspressoIdlingResource; @@ -45,11 +45,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Set; public class TransferMethodConfigurationRepositoryImpl implements TransferMethodConfigurationRepository { - private HyperwalletTransferMethodConfigurationKeyResult mTransferMethodConfigurationKeyResult; + private HyperwalletTransferMethodConfigurationKey mTransferMethodConfigurationKey; private final Handler mHandler; - private final Map mFieldMap; + private final Map mFieldMap; TransferMethodConfigurationRepositoryImpl() { mHandler = new Handler(); @@ -63,11 +64,10 @@ Hyperwallet getHyperwallet() { @VisibleForTesting() protected TransferMethodConfigurationRepositoryImpl(@Nullable Handler handler, - HyperwalletTransferMethodConfigurationKeyResult - transferMethodConfigurationKeyResult, Map fieldMap) { + HyperwalletTransferMethodConfigurationKey transferMethodConfigurationKey, + Map fieldMap) { mHandler = handler; - mTransferMethodConfigurationKeyResult = transferMethodConfigurationKeyResult; + mTransferMethodConfigurationKey = transferMethodConfigurationKey; mFieldMap = fieldMap; } @@ -77,11 +77,11 @@ void getTransferMethodConfigurationKeyResult(final LoadKeysCallback loadKeysCall EspressoIdlingResource.increment(); getHyperwallet().retrieveTransferMethodConfigurationKeys(query, - new HyperwalletListener() { + new HyperwalletListener() { @Override - public void onSuccess(@Nullable HyperwalletTransferMethodConfigurationKeyResult result) { - mTransferMethodConfigurationKeyResult = result; - loadKeysCallback.onKeysLoaded(mTransferMethodConfigurationKeyResult); + public void onSuccess(@Nullable HyperwalletTransferMethodConfigurationKey result) { + mTransferMethodConfigurationKey = result; + loadKeysCallback.onKeysLoaded(mTransferMethodConfigurationKey); EspressoIdlingResource.decrement(); } @@ -106,18 +106,19 @@ void getTransferMethodConfigurationFieldResult(@NonNull final String country, @NonNull final String transferMethodProfileType, @NonNull final LoadFieldsCallback loadFieldsCallback) { HyperwalletTransferMethodConfigurationFieldQuery query = - new HyperwalletTransferMethodConfigurationFieldQuery(country, currency, transferMethodType, - transferMethodProfileType); + new HyperwalletTransferMethodConfigurationFieldQuery(country, currency, + transferMethodType, transferMethodProfileType); EspressoIdlingResource.increment(); getHyperwallet().retrieveTransferMethodConfigurationFields( query, - new HyperwalletListener() { + new HyperwalletListener() { @Override - public void onSuccess(HyperwalletTransferMethodConfigurationFieldResult result) { + public void onSuccess(HyperwalletTransferMethodConfigurationField result) { FieldMapKey fieldMapKey = new FieldMapKey(country, currency, transferMethodType); mFieldMap.put(fieldMapKey, result); - loadFieldsCallback.onFieldsLoaded(result); + loadFieldsCallback.onFieldsLoaded(result, + getProcessingTime(country, currency, transferMethodType)); EspressoIdlingResource.decrement(); } @@ -137,10 +138,10 @@ public Handler getHandler() { @Override public synchronized void getKeys(@NonNull final LoadKeysCallback loadKeysCallback) { - if (mTransferMethodConfigurationKeyResult == null) { + if (mTransferMethodConfigurationKey == null) { getTransferMethodConfigurationKeyResult(loadKeysCallback); } else { - loadKeysCallback.onKeysLoaded(mTransferMethodConfigurationKeyResult); + loadKeysCallback.onKeysLoaded(mTransferMethodConfigurationKey); } } @@ -149,27 +150,45 @@ public synchronized void getFields(@NonNull final String country, @NonNull final @NonNull final String transferMethodType, @NonNull final String transferMethodProfileType, @NonNull final LoadFieldsCallback loadFieldsCallback) { + FieldMapKey fieldMapKey = new FieldMapKey(country, currency, transferMethodType); - HyperwalletTransferMethodConfigurationFieldResult transferMethodConfigurationFieldResult = mFieldMap.get( - fieldMapKey); + HyperwalletTransferMethodConfigurationField transferMethodConfigurationField = mFieldMap.get(fieldMapKey); // if there is no value for country-currency-type combination, // it means api call was never made or this combination or it was refreshed - if (transferMethodConfigurationFieldResult == null) { - getTransferMethodConfigurationFieldResult(country, currency, transferMethodType, transferMethodProfileType, loadFieldsCallback); + if (transferMethodConfigurationField == null) { + getTransferMethodConfigurationFieldResult(country, currency, transferMethodType, + transferMethodProfileType, loadFieldsCallback); } else { - loadFieldsCallback.onFieldsLoaded(transferMethodConfigurationFieldResult); + loadFieldsCallback.onFieldsLoaded(transferMethodConfigurationField, + getProcessingTime(country, currency, transferMethodType)); } } @Override public void refreshKeys() { - mTransferMethodConfigurationKeyResult = null; + mTransferMethodConfigurationKey = null; } @Override public void refreshFields() { mFieldMap.clear(); } + + //TODO this method is just temporary, placed to get the processing time + //Next iteration from API will have ProcessingTime as a separate node + @Nullable + private String getProcessingTime(String country, String currency, String transferMethodType) { + if (mTransferMethodConfigurationKey != null) { + Set transferMethodTypes = mTransferMethodConfigurationKey + .getTransferMethodType(country, currency); + for (HyperwalletTransferMethodType type : transferMethodTypes) { + if (type.getName().equals(transferMethodType)) { + return type.getProcessingTime(); + } + } + } + return null; + } } class FieldMapKey { @@ -213,6 +232,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(mCountry, mCurrency, mTransferMethodType); } - - } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepository.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepository.java index 46d5ec781..de222ff69 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepository.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepository.java @@ -39,11 +39,11 @@ void createTransferMethod(@NonNull HyperwalletTransferMethod transferMethod, @NonNull LoadTransferMethodCallback callback); /** - * Load transfe methods available associated with current context + * Load transfer methods available associated with current context * * @param callback @see {@link LoadTransferMethodListCallback} */ - void loadTransferMethod(@NonNull LoadTransferMethodListCallback callback); + void loadTransferMethods(@NonNull LoadTransferMethodListCallback callback); /** * Deactivate transfer method specified. diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java index 7bc72f0c9..4becad682 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java @@ -65,7 +65,7 @@ public void createTransferMethod(@NonNull final HyperwalletTransferMethod transf } @Override - public void loadTransferMethod(@NonNull final LoadTransferMethodListCallback callback) { + public void loadTransferMethods(@NonNull final LoadTransferMethodListCallback callback) { getHyperwallet().listTransferMethods(null, new HyperwalletListener>() { @Override diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodContract.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodContract.java index 93f3aa9da..eb3e29810 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodContract.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodContract.java @@ -20,8 +20,8 @@ import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletTransferMethod; -import com.hyperwallet.android.model.meta.Fee; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.HyperwalletFee; +import com.hyperwallet.android.model.meta.field.HyperwalletFieldGroup; import java.util.List; @@ -38,9 +38,9 @@ interface View { void showErrorLoadTransferMethodConfigurationFields(@NonNull final List errors); - void showTransferMethodFields(@NonNull final List fields); + void showTransferMethodFields(@NonNull final List fields); - void showTransactionInformation(List fees, String processingTime); + void showTransactionInformation(List fees, String processingTime); void showCreateButtonProgressBar(); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java index 2507c3eed..659e6a205 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java @@ -16,6 +16,7 @@ */ package com.hyperwallet.android.ui.transfermethod; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.PROFILE_TYPE; import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_COUNTRY; import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_CURRENCY; import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TYPE; @@ -50,8 +51,9 @@ import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletTransferMethod; import com.hyperwallet.android.model.PayPalAccount; -import com.hyperwallet.android.model.meta.Fee; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.HyperwalletFee; +import com.hyperwallet.android.model.meta.field.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletFieldGroup; import com.hyperwallet.android.ui.HyperwalletLocalBroadcast; import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.ui.view.WidgetSelectionDialogFragment; @@ -92,7 +94,6 @@ public class AddTransferMethodFragment extends Fragment implements WidgetEventLi private HyperwalletTransferMethod mTransferMethod; private String mTransferMethodProfileType; private HashMap mWidgetInputStateHashMap; - private TextView sectionHeaderTextView; /** * Please do not use this to have instance of AddTransferMethodFragment this is reserved for android framework @@ -176,8 +177,6 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); mDynamicContainer = view.findViewById(R.id.add_transfer_method_dynamic_container); - sectionHeaderTextView = view.findViewById(R.id.account_information_section_header); - mCreateButtonProgressBar = view.findViewById(R.id.add_transfer_method_create_button_progress_bar); mProgressBar = view.findViewById(R.id.add_transfer_method_progress_bar_layout); @@ -211,6 +210,7 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { mCountry = savedInstanceState.getString(ARGUMENT_TRANSFER_METHOD_COUNTRY); mCurrency = savedInstanceState.getString(ARGUMENT_TRANSFER_METHOD_CURRENCY); mTransferMethodType = savedInstanceState.getString(ARGUMENT_TRANSFER_METHOD_TYPE); + mTransferMethodProfileType = savedInstanceState.getString(ARGUMENT_TRANSFER_METHOD_PROFILE_TYPE); mShowCreateProgressBar = savedInstanceState.getBoolean(ARGUMENT_SHOW_CREATE_PROGRESS_BAR); mTransferMethod = savedInstanceState.getParcelable(ARGUMENT_TRANSFER_METHOD); } else { // same as AddTransferMethodFragment#newInstance @@ -218,12 +218,9 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { mCountry = getArguments().getString(ARGUMENT_TRANSFER_METHOD_COUNTRY); mCurrency = getArguments().getString(ARGUMENT_TRANSFER_METHOD_CURRENCY); mTransferMethodType = getArguments().getString(ARGUMENT_TRANSFER_METHOD_TYPE); + mTransferMethodProfileType = getArguments().getString(ARGUMENT_TRANSFER_METHOD_PROFILE_TYPE); mTransferMethod = getArguments().getParcelable(ARGUMENT_TRANSFER_METHOD); } - - Locale locale = new Locale.Builder().setRegion(mCountry).build(); - sectionHeaderTextView.setText(requireContext().getResources() - .getString(R.string.account_information_section_header, locale.getDisplayName(), mCurrency)); } @Override @@ -244,6 +241,7 @@ public void onSaveInstanceState(@NonNull Bundle outState) { outState.putString(ARGUMENT_TRANSFER_METHOD_COUNTRY, mCountry); outState.putString(ARGUMENT_TRANSFER_METHOD_CURRENCY, mCurrency); outState.putString(ARGUMENT_TRANSFER_METHOD_TYPE, mTransferMethodType); + outState.putString(ARGUMENT_TRANSFER_METHOD_PROFILE_TYPE, mTransferMethodProfileType); outState.putBoolean(ARGUMENT_SHOW_CREATE_PROGRESS_BAR, mShowCreateProgressBar); outState.putParcelable(ARGUMENT_TRANSFER_METHOD, mTransferMethod); super.onSaveInstanceState(outState); @@ -298,26 +296,37 @@ public void notifyTransferMethodAdded(@NonNull final HyperwalletTransferMethod t } @Override - public void showTransferMethodFields(@NonNull final List fields) { + public void showTransferMethodFields(@NonNull final List fields) { mDynamicContainer.removeAllViews(); - int previousView = 0; + try { - for (final HyperwalletField field : fields) { - AbstractWidget widget = WidgetFactory - .newWidget(field, this, getContext(), - mWidgetInputStateHashMap.containsKey(field.getName()) ? - mWidgetInputStateHashMap.get(field.getName()).getValue() : "", - mCreateTransferMethodButton); - if (mWidgetInputStateHashMap.isEmpty() || !mWidgetInputStateHashMap.containsKey(widget.getName())) { - mWidgetInputStateHashMap.put(widget.getName(), widget.getWidgetInputState()); - } + Locale locale = new Locale.Builder().setRegion(mCountry).build(); + // group + for (HyperwalletFieldGroup group : fields) { + View sectionHeader = LayoutInflater.from(mDynamicContainer.getContext()) + .inflate(R.layout.item_widget_section_header, mDynamicContainer, false); + TextView sectionTitle = sectionHeader.findViewById(R.id.section_header_title); + sectionTitle.setText(getSectionHeaderText(group, locale)); + sectionHeader.setId(View.generateViewId()); + mDynamicContainer.addView(sectionHeader); + + // group fields + for (final HyperwalletField field : group.getFields()) { + AbstractWidget widget = WidgetFactory + .newWidget(field, this, mWidgetInputStateHashMap.containsKey(field.getName()) ? + mWidgetInputStateHashMap.get(field.getName()).getValue() : "", + mCreateTransferMethodButton); + if (mWidgetInputStateHashMap.isEmpty() || !mWidgetInputStateHashMap.containsKey(widget.getName())) { + mWidgetInputStateHashMap.put(widget.getName(), widget.getWidgetInputState()); + } - View widgetView = widget.getView(); - widgetView.setTag(widget); - previousView = placeBelow(widgetView, previousView, true); - final String error = mWidgetInputStateHashMap.get(widget.getName()).getErrorMessage(); - widget.showValidationError(error); - mDynamicContainer.addView(widgetView); + View widgetView = widget.getView(mDynamicContainer); + widgetView.setTag(widget); + widgetView.setId(View.generateViewId()); + final String error = mWidgetInputStateHashMap.get(widget.getName()).getErrorMessage(); + widget.showValidationError(error); + mDynamicContainer.addView(widgetView); + } } if (mShowCreateProgressBar) { @@ -328,8 +337,20 @@ public void showTransferMethodFields(@NonNull final List field } } + private String getSectionHeaderText(@NonNull final HyperwalletFieldGroup group, @NonNull final Locale locale) { + if (group.getGroupName().equals(HyperwalletFieldGroup.GroupTypes.ACCOUNT_INFORMATION)) { + return requireContext().getResources() + .getString(R.string.account_information_section_header, locale.getDisplayName(), mCurrency); + } + + return requireContext().getString(requireContext().getResources() + .getIdentifier(group.getGroupName().toLowerCase(Locale.ROOT), "string", + requireContext().getPackageName())); + } + @Override - public void showTransactionInformation(@NonNull final List fees, @Nullable final String processingTime) { + public void showTransactionInformation(@NonNull final List fees, + @Nullable final String processingTime) { View header = getView().findViewById(R.id.add_transfer_method_static_container_header); View container = getView().findViewById(R.id.add_transfer_method_static_container); View feeLabel = getView().findViewById(R.id.add_transfer_method_fee_label); @@ -339,7 +360,7 @@ public void showTransactionInformation(@NonNull final List fees, @Nullable int defaultMargin = (int) requireContext().getResources().getDimension(R.dimen.default_margin); - if (!fees.isEmpty()) { + if (fees != null && !fees.isEmpty()) { String formattedFee = FeeFormatter.getFormattedFee(requireContext(), fees); feeValue.setText(formattedFee); feeLabel.setVisibility(View.VISIBLE); @@ -420,7 +441,7 @@ public void showInputErrors(List errors) { AbstractWidget widget = (AbstractWidget) view.getTag(); if (widget.getName().equals(error.getFieldName())) { if (!focusSet) { - widget.getView().requestFocus(); + widget.getView(mDynamicContainer).requestFocus(); focusSet = true; } widget.showValidationError(error.getMessage()); @@ -497,6 +518,8 @@ private void triggerSubmit() { mTransferMethod.setField(widget.getName(), widget.getValue()); } } + + mTransferMethod.setField(PROFILE_TYPE, mTransferMethodProfileType); mPresenter.createTransferMethod(mTransferMethod); } } @@ -524,25 +547,6 @@ private void setVisibleAndDisableFields() { mCreateTransferMethodButton.setBackgroundColor(getResources().getColor(R.color.colorSecondaryDark)); } - private int placeBelow(View v, int previousId, boolean matchParentWidth) { - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( - matchParentWidth ? ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - - if (previousId != 0) { - params.addRule(RelativeLayout.BELOW, previousId); - } - - int margin = (int) (getContext().getResources().getDimension(R.dimen.default_margin) - / getContext().getResources().getDisplayMetrics().density); - - params.setMargins(margin, margin, margin, margin); - v.setId(View.generateViewId()); - v.setLayoutParams(params); - - return v.getId(); - } - private boolean performValidation(boolean bypassFocusCheck) { boolean valid = true; // this is added since some phones triggers the create button but the widgets are not yet initialized @@ -569,16 +573,7 @@ private boolean performValidation(boolean bypassFocusCheck) { } } } - return valid && hasWidget && haveAllWidgetsReceivedFocus(); - } - - private boolean haveAllWidgetsReceivedFocus() { - for (String key : mWidgetInputStateHashMap.keySet()) { - if (!mWidgetInputStateHashMap.get(key).hasFocused()) { - return false; - } - } - return true; + return valid && hasWidget; } @Override diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodPresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodPresenter.java index 73b10717d..8373668bd 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodPresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodPresenter.java @@ -17,16 +17,14 @@ package com.hyperwallet.android.ui.transfermethod; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.HyperwalletTransferMethod; -import com.hyperwallet.android.model.meta.Fee; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationFieldResult; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationField; import com.hyperwallet.android.ui.repository.TransferMethodConfigurationRepository; import com.hyperwallet.android.ui.repository.TransferMethodRepository; -import java.util.List; - public class AddTransferMethodPresenter implements AddTransferMethodContract.Presenter { private static final String TAG = AddTransferMethodContract.class.getName(); @@ -87,21 +85,16 @@ public void loadTransferMethodConfigurationFields(final boolean forceUpdate, @No country, currency, transferMethodType, transferMethodProfileType, new TransferMethodConfigurationRepository.LoadFieldsCallback() { @Override - public void onFieldsLoaded( - HyperwalletTransferMethodConfigurationFieldResult transferMethodConfigurationFieldResult) { + public void onFieldsLoaded(HyperwalletTransferMethodConfigurationField field, + @Nullable final String processingTime) { if (!mView.isActive()) { return; } mView.hideProgressBar(); - mView.showTransferMethodFields(transferMethodConfigurationFieldResult.getFields()); + mView.showTransferMethodFields(field.getFields().getFieldGroups()); // there can be multiple fees when we have flat fee + percentage fees - List fees = transferMethodConfigurationFieldResult - .getFees(country, currency, transferMethodType, transferMethodProfileType); - mView.showTransactionInformation(fees, - transferMethodConfigurationFieldResult - .getProcessingTime(country, currency, transferMethodType, - transferMethodProfileType)); + mView.showTransactionInformation(field.getFees(), processingTime); } @Override diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java index 95cf1cf22..095c218c7 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java @@ -23,13 +23,13 @@ import androidx.annotation.NonNull; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.Fee; +import com.hyperwallet.android.model.meta.HyperwalletFee; import java.util.List; public class FeeFormatter { - public static String getFormattedFee(@NonNull final Context context, @NonNull final List fees) { + public static String getFormattedFee(@NonNull final Context context, @NonNull final List fees) { String formattedString = context.getResources().getString(R.string.unknown); if (fees.size() == 1) { formattedString = getSingleFormattedFee(context, fees, formattedString); @@ -39,13 +39,13 @@ public static String getFormattedFee(@NonNull final Context context, @NonNull fi return formattedString; } - private static String getSingleFormattedFee(@NonNull Context context, @NonNull List fees, + private static String getSingleFormattedFee(@NonNull Context context, @NonNull List fees, String formattedString) { - Fee fee = fees.get(0); - if (Fee.FeeRate.FLAT.equals(fee.getFeeRateType())) { + HyperwalletFee fee = fees.get(0); + if (HyperwalletFee.FeeRate.FLAT.equals(fee.getFeeRateType())) { formattedString = context.getResources().getString(R.string.fee_flat_formatter, fee.getCurrency(), fee.getValue()); - } else if (Fee.FeeRate.PERCENT.equals(fee.getFeeRateType())) { + } else if (HyperwalletFee.FeeRate.PERCENT.equals(fee.getFeeRateType())) { formattedString = getPercentFormattedFee(context, fee); } return formattedString; @@ -53,20 +53,20 @@ private static String getSingleFormattedFee(@NonNull Context context, @NonNull L // we expect at the most 2 fees and in that case one should be flat and other percent // which will be formatted to USD 3.00 + 3% (Min: USD 1.00, Max: USD 15.00) - private static String getMixFormattedFee(@NonNull Context context, @NonNull List fees, + private static String getMixFormattedFee(@NonNull Context context, @NonNull List fees, String formattedString) { - Fee flatFee = null; - Fee percentFee = null; - for (Fee fee : fees) { - if (Fee.FeeRate.FLAT.equals(fee.getFeeRateType())) { + HyperwalletFee flatFee = null; + HyperwalletFee percentFee = null; + for (HyperwalletFee fee : fees) { + if (HyperwalletFee.FeeRate.FLAT.equals(fee.getFeeRateType())) { flatFee = fee; - } else if (Fee.FeeRate.PERCENT.equals(fee.getFeeRateType())) { + } else if (HyperwalletFee.FeeRate.PERCENT.equals(fee.getFeeRateType())) { percentFee = fee; } } if (flatFee != null && percentFee != null) { - String minimumAmount = percentFee.getMinimum(); - String maximumAmount = percentFee.getMaximum(); + String minimumAmount = percentFee.getMin(); + String maximumAmount = percentFee.getMax(); if (maximumAmount.isEmpty() && minimumAmount.isEmpty()) { formattedString = context.getResources().getString(R.string.fee_mix_no_min_and_max_formatter, flatFee.getCurrency(), flatFee.getValue(), percentFee.getValue()); @@ -85,10 +85,10 @@ private static String getMixFormattedFee(@NonNull Context context, @NonNull List } - private static String getPercentFormattedFee(@NonNull final Context context, @NonNull final Fee fee) { + private static String getPercentFormattedFee(@NonNull final Context context, @NonNull final HyperwalletFee fee) { String formattedFee; - String minimumAmount = fee.getMinimum(); - String maximumAmount = fee.getMaximum(); + String minimumAmount = fee.getMin(); + String maximumAmount = fee.getMax(); if (maximumAmount.isEmpty() && minimumAmount.isEmpty()) { formattedFee = context.getResources().getString(R.string.fee_percent_no_min_and_max_formatter, fee.getValue()); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodPresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodPresenter.java index ece9b89d9..5480e0a2e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodPresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodPresenter.java @@ -38,7 +38,7 @@ public ListTransferMethodPresenter(TransferMethodRepository repository, ListTran @Override public void loadTransferMethods() { mView.showProgressBar(); - mTransferMethodRepository.loadTransferMethod(new TransferMethodRepository.LoadTransferMethodListCallback() { + mTransferMethodRepository.loadTransferMethods(new TransferMethodRepository.LoadTransferMethodListCallback() { @Override public void onTransferMethodListLoaded(List transferMethods) { if (!mView.isActive()) { diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java index db873d8f7..193aefd14 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java @@ -19,7 +19,6 @@ package com.hyperwallet.android.ui.transfermethod; import static com.hyperwallet.android.ui.transfermethod.TransferMethodUtils.getStringFontIcon; -import static com.hyperwallet.android.ui.transfermethod.TransferMethodUtils.getStringResourceByName; import android.annotation.SuppressLint; import android.content.Context; @@ -457,8 +456,7 @@ class ViewHolder extends RecyclerView.ViewHolder { @SuppressLint("StringFormatInvalid") void bind(TransferMethodSelectionItem selectionItem) { - mTitle.setText( - getStringResourceByName(mTitle.getContext(), selectionItem.getTransferMethodType())); + mTitle.setText(selectionItem.getTransferMethodName()); mIcon.setText( getStringFontIcon(mIcon.getContext(), selectionItem.getTransferMethodType())); @@ -466,6 +464,7 @@ void bind(TransferMethodSelectionItem selectionItem) { String formattedFee = FeeFormatter.getFormattedFee(mTitle.getContext(), selectionItem.getFees()); mDescriptionFees.setText(mDescriptionFees.getContext() .getString(R.string.select_transfer_method_item_fee_information, formattedFee)); + mDescriptionFees.setVisibility(View.VISIBLE); } else { mDescriptionFees.setVisibility(View.GONE); } @@ -474,6 +473,7 @@ void bind(TransferMethodSelectionItem selectionItem) { mDescriptionProcessingTime.setText(mDescriptionProcessingTime.getContext() .getString(R.string.select_transfer_method_item_processing_time_information, selectionItem.getProcessingTime())); + mDescriptionProcessingTime.setVisibility(View.VISIBLE); } else { mDescriptionProcessingTime.setVisibility(View.INVISIBLE); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodPresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodPresenter.java index 4524e8ff0..e5e49cb59 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodPresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodPresenter.java @@ -15,7 +15,6 @@ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ - package com.hyperwallet.android.ui.transfermethod; import androidx.annotation.NonNull; @@ -23,15 +22,17 @@ import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.HyperwalletUser; -import com.hyperwallet.android.model.meta.Fee; -import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKeyResult; +import com.hyperwallet.android.model.meta.HyperwalletTransferMethodConfigurationKey; +import com.hyperwallet.android.model.meta.keyed.Country; +import com.hyperwallet.android.model.meta.keyed.Currency; +import com.hyperwallet.android.model.meta.keyed.HyperwalletTransferMethodType; import com.hyperwallet.android.ui.repository.TransferMethodConfigurationRepository; import com.hyperwallet.android.ui.repository.UserRepository; import java.util.ArrayList; -import java.util.Currency; +import java.util.HashSet; import java.util.List; -import java.util.Locale; +import java.util.Set; import java.util.TreeMap; public class SelectTransferMethodPresenter implements SelectTransferMethodContract.Presenter { @@ -64,20 +65,21 @@ public void onUserLoaded(@NonNull final HyperwalletUser user) { mTransferMethodConfigurationRepository.getKeys( new TransferMethodConfigurationRepository.LoadKeysCallback() { @Override - public void onKeysLoaded( - @Nullable final HyperwalletTransferMethodConfigurationKeyResult transferMethodConfigurationKeyResult) { + public void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKey key) { if (!mView.isActive()) { return; } mView.hideProgressBar(); - List transferMethodTypes = - transferMethodConfigurationKeyResult.getTransferMethods(countryCode, - currencyCode, user.getProfileType()); + Set transferMethodTypes = + key.getTransferMethodType(countryCode, currencyCode) != null + ? key.getTransferMethodType(countryCode, currencyCode) : + new HashSet(); mView.showTransferMethodCountry(countryCode); mView.showTransferMethodCurrency(currencyCode); - mView.showTransferMethodTypes(getTransferMethodSelectionItems(countryCode, currencyCode, - user.getProfileType(), transferMethodTypes, transferMethodConfigurationKeyResult)); + mView.showTransferMethodTypes( + getTransferMethodSelectionItems(countryCode, currencyCode, + user.getProfileType(), transferMethodTypes)); } @Override @@ -110,24 +112,28 @@ public void loadCurrency(final boolean forceUpdate, @NonNull final String countr } mUserRepository.loadUser(new UserRepository.LoadUserCallback() { - @Override public void onUserLoaded(@NonNull final HyperwalletUser user) { mTransferMethodConfigurationRepository.getKeys( new TransferMethodConfigurationRepository.LoadKeysCallback() { @Override - public void onKeysLoaded( - @Nullable final HyperwalletTransferMethodConfigurationKeyResult result) { + public void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKey key) { if (!mView.isActive()) { return; } - List transferMethodCurrencies = result.getCurrencies(countryCode); - List transferMethodTypes = result.getTransferMethods( - countryCode, transferMethodCurrencies.get(0), user.getProfileType()); + List currencies = key.getCurrencies(countryCode) != null ? + new ArrayList<>(key.getCurrencies(countryCode)) : + new ArrayList(); + String currencyCode = currencies.get(0).getCode(); + Set transferMethodTypes = + key.getTransferMethodType(countryCode, currencyCode) != null ? + key.getTransferMethodType(countryCode, currencyCode) : + new HashSet(); mView.showTransferMethodCountry(countryCode); - mView.showTransferMethodCurrency(transferMethodCurrencies.get(0)); + mView.showTransferMethodCurrency(currencies.get(0).getCode()); mView.showTransferMethodTypes(getTransferMethodSelectionItems(countryCode, - transferMethodCurrencies.get(0), user.getProfileType(), transferMethodTypes, result)); + currencies.get(0).getCode(), + user.getProfileType(), transferMethodTypes)); } @Override @@ -142,7 +148,6 @@ public void onError(@NonNull HyperwalletErrors errors) { showErrorLoadCurrency(errors); } }); - } private void showErrorLoadCurrency(@NonNull HyperwalletErrors errors) { @@ -165,20 +170,20 @@ public void onUserLoaded(@NonNull final HyperwalletUser user) { mTransferMethodConfigurationRepository.getKeys( new TransferMethodConfigurationRepository.LoadKeysCallback() { @Override - public void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKeyResult - transferMethodConfigurationKeyResult) { + public void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKey key) { if (!mView.isActive()) { return; } - List transferMethodTypes = - transferMethodConfigurationKeyResult.getTransferMethods( - countryCode, currencyCode, user.getProfileType()); - + Set transferMethodTypes = + key.getTransferMethodType(countryCode, currencyCode) != null ? + key.getTransferMethodType(countryCode, currencyCode) : + new HashSet(); mView.showTransferMethodCountry(countryCode); mView.showTransferMethodCurrency(currencyCode); - mView.showTransferMethodTypes(getTransferMethodSelectionItems(countryCode, currencyCode, - user.getProfileType(), transferMethodTypes, transferMethodConfigurationKeyResult)); + mView.showTransferMethodTypes( + getTransferMethodSelectionItems(countryCode, currencyCode, + user.getProfileType(), transferMethodTypes)); } @Override @@ -199,7 +204,6 @@ public void onError(@NonNull HyperwalletErrors errors) { mView.showErrorLoadTransferMethodTypes(errors.getErrors()); } }); - } @Override @@ -212,21 +216,21 @@ public void openAddTransferMethod(@NonNull final String country, @NonNull final public void loadCountrySelection(@NonNull final String countryCode) { mTransferMethodConfigurationRepository.getKeys(new TransferMethodConfigurationRepository.LoadKeysCallback() { @Override - public void onKeysLoaded( - @Nullable final HyperwalletTransferMethodConfigurationKeyResult transferMethodConfigurationKeyResult) { + public void onKeysLoaded(@Nullable final HyperwalletTransferMethodConfigurationKey key) { if (!mView.isActive()) { return; } - List countryCodes = transferMethodConfigurationKeyResult.getCountries(); + Set countries = key.getCountries(); TreeMap countryNameCodeMap = new TreeMap<>(); - Locale.Builder builder = new Locale.Builder(); - for (String countryCode : countryCodes) { - Locale locale = builder.setRegion(countryCode).build(); - countryNameCodeMap.put(locale.getDisplayName(), countryCode); + String selectedCountryName = ""; + for (Country country : countries) { + if (country.getCode().equals(countryCode)) { + selectedCountryName = country.getName(); + } + countryNameCodeMap.put(country.getName(), country.getCode()); } - Locale locale = new Locale.Builder().setRegion(countryCode).build(); - mView.showCountrySelectionDialog(countryNameCodeMap, locale.getDisplayName()); + mView.showCountrySelectionDialog(countryNameCodeMap, selectedCountryName); } @Override @@ -242,20 +246,23 @@ public void onError(@NonNull final HyperwalletErrors errors) { public void loadCurrencySelection(@NonNull final String countryCode, @NonNull final String currencyCode) { mTransferMethodConfigurationRepository.getKeys(new TransferMethodConfigurationRepository.LoadKeysCallback() { @Override - public void onKeysLoaded( - @Nullable HyperwalletTransferMethodConfigurationKeyResult transferMethodConfigurationKeyResult) { + public void onKeysLoaded(@Nullable HyperwalletTransferMethodConfigurationKey key) { if (!mView.isActive()) { return; } - List currencyCodes = transferMethodConfigurationKeyResult.getCurrencies(countryCode); + Set currencyCodes = key.getCurrencies(countryCode) != null ? + key.getCurrencies(countryCode) : new HashSet(); + TreeMap currencyNameCodeMap = new TreeMap<>(); - for (String currencyCode : currencyCodes) { - Currency currency = Currency.getInstance(currencyCode); - currencyNameCodeMap.put(currency.getDisplayName(), currencyCode); + String selectedCurrencyName = ""; + for (Currency currency : currencyCodes) { + if (currency.getCode().equals(currencyCode)) { + selectedCurrencyName = currency.getName(); + } + currencyNameCodeMap.put(currency.getName(), currency.getCode()); } - mView.showCurrencySelectionDialog(currencyNameCodeMap, - Currency.getInstance(currencyCode).getDisplayName()); + mView.showCurrencySelectionDialog(currencyNameCodeMap, selectedCurrencyName); } @Override @@ -269,20 +276,17 @@ public void onError(@NonNull final HyperwalletErrors errors) { } private List getTransferMethodSelectionItems( - @NonNull final String country, @NonNull final String currency, + @NonNull final String countryCode, @NonNull final String currencyCode, @NonNull final String userProfileType, - @NonNull final List transferMethodTypes, - @NonNull final HyperwalletTransferMethodConfigurationKeyResult result) { + @NonNull final Set transferMethodTypes) { List selectionItems = new ArrayList<>(); - for (String transferMethodType : transferMethodTypes) { - List fees = result.getFees(country, currency, transferMethodType, userProfileType); - String processingTime = result.getProcessingTime(country, currency, transferMethodType, userProfileType); - TransferMethodSelectionItem data = new TransferMethodSelectionItem(country, currency, userProfileType, - transferMethodType, processingTime, fees); + for (HyperwalletTransferMethodType transferMethodType : transferMethodTypes) { + TransferMethodSelectionItem data = new TransferMethodSelectionItem(countryCode, currencyCode, + userProfileType, transferMethodType.getCode(), transferMethodType.getName(), + transferMethodType.getProcessingTime(), transferMethodType.getFees()); selectionItems.add(data); } return selectionItems; } - } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSelectionItem.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSelectionItem.java index d065d7ac1..c3c7af373 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSelectionItem.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSelectionItem.java @@ -18,29 +18,34 @@ import androidx.annotation.NonNull; -import com.hyperwallet.android.model.meta.Fee; +import com.hyperwallet.android.model.meta.HyperwalletFee; +import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Set; public class TransferMethodSelectionItem { private final String mCountry; private final String mCurrency; - private final List mFees; + private final List mFees; private final String mProcessingTime; private final String mProfileType; private final String mTransferMethodType; + private final String mTransferMethodName; public TransferMethodSelectionItem(@NonNull final String country, @NonNull final String currency, @NonNull final String profileType, @NonNull final String transferMethodType, - @NonNull final String processingTime, @NonNull final List fees) { + @NonNull final String transferMethodName, @NonNull final String processingTime, + @NonNull final Set fees) { mCountry = country; mCurrency = currency; mProfileType = profileType; mTransferMethodType = transferMethodType; + mTransferMethodName = transferMethodName; mProcessingTime = processingTime; - mFees = fees; + mFees = new ArrayList<>(fees); } public String getCountry() { @@ -55,6 +60,10 @@ public String getProfileType() { return mProfileType; } + public String getTransferMethodName() { + return mTransferMethodName; + } + public String getTransferMethodType() { return mTransferMethodType; } @@ -63,7 +72,7 @@ public String getProcessingTime() { return mProcessingTime; } - public List getFees() { + public List getFees() { return mFees; } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java index 7bed35b21..5dab1341b 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java @@ -16,19 +16,27 @@ */ package com.hyperwallet.android.ui.view; +import android.app.SearchManager; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; @@ -41,19 +49,23 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.TreeMap; public class WidgetSelectionDialogFragment extends DialogFragment implements ToolbarEventListener { public static final String TAG = WidgetSelectionDialogFragment.class.getName(); private static final String ARGUMENT_NAME_VALUE_MAP = "ARGUMENT_NAME_VALUE_MAP"; + private static final String ARGUMENT_SEARCH_SELECTED_NAME_QUERY = "ARGUMENT_SEARCH_SELECTED_NAME_QUERY"; private static final String ARGUMENT_SELECTED_NAME = "ARGUMENT_SELECTED_NAME"; private static final String ARGUMENT_SELECTION_LABEL = "ARGUMENT_SELECTION_LABEL"; private static final String ARGUMENT_SELECTION_FIELD_NAME = "ARGUMENT_SELECTION_FIELD_NAME"; + private static final int MAX_NO_SEARCH_COUNT = 20; private Adapter mAdapter; private String mFieldName; private TreeMap mNameValueMap; + private String mSearchNameQuery; private String mSelectedName; private String mSelectionLabel; private WidgetSelectionItemListener mWidgetSelectionItemListener; @@ -66,12 +78,14 @@ public static WidgetSelectionDialogFragment newInstance(@NonNull final TreeMap MAX_NO_SEARCH_COUNT); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.clear(); + inflater.inflate(R.menu.menu_widget_selection, menu); + + SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE); + MenuItem searchItem = menu.findItem(R.id.widget_selection_search_item); + SearchView searchView = (SearchView) searchItem.getActionView(); + searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName())); + searchView.setMaxWidth(Integer.MAX_VALUE); + searchView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + mSearchNameQuery = query; + mAdapter.getFilter().filter(query); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + mSearchNameQuery = newText; + mAdapter.getFilter().filter(newText); + return false; + } + }); + + if (!mSearchNameQuery.isEmpty()) { + searchView.clearFocus(); + searchItem.expandActionView(); + searchView.setQuery(mSearchNameQuery, true); } } @@ -181,15 +232,16 @@ public interface WidgetSelectionItemListener { void onWidgetSelectionItemClicked(@NonNull final String selectedValue, @NonNull final String fieldName); } - private static class Adapter extends RecyclerView.Adapter { + private static class Adapter extends RecyclerView.Adapter implements Filterable { + private final Fragment mFragment; + private final String mFieldName; private final TreeMap mNameValueMap; private final String mSelectedName; - private final List mSelectionList; private final ToolbarEventListener mToolbarEventListener; - private final Fragment mFragment; - private final String mFieldName; private final WidgetSelectionItemListener mWidgetSelectionItemListener; + private TreeMap mNameValueFilteredMap; + private List mSelectionList; Adapter(@NonNull final TreeMap nameValueMap, @NonNull final String selectedName, @NonNull final Fragment fragment, @NonNull final ToolbarEventListener toolbarEventListener, @@ -198,6 +250,7 @@ private static class Adapter extends RecyclerView.Adapter { mSelectionList = new ArrayList<>(nameValueMap.keySet()); mSelectedName = selectedName; mNameValueMap = nameValueMap; + mNameValueFilteredMap = nameValueMap; mToolbarEventListener = toolbarEventListener; mFragment = fragment; mFieldName = fieldName; @@ -243,6 +296,37 @@ String getItemValue(int position) { return mNameValueMap.get(mSelectionList.get(position)); } + @Override + public Filter getFilter() { + return new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + if (constraint.length() == 0) { + mSelectionList = new ArrayList<>(mNameValueMap.keySet()); + mNameValueFilteredMap = mNameValueMap; + } else { + mNameValueFilteredMap = new TreeMap<>(); + for (String selection : mNameValueMap.keySet()) { + if (selection.toLowerCase(Locale.ROOT) + .contains(constraint.toString().toLowerCase(Locale.ROOT))) { + mNameValueFilteredMap.put(selection, mNameValueMap.get(selection)); + } + } + mSelectionList = new ArrayList<>(mNameValueFilteredMap.keySet()); + } + FilterResults filterResults = new FilterResults(); + filterResults.values = mNameValueFilteredMap; + return filterResults; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + mNameValueFilteredMap = (TreeMap) results.values; + notifyDataSetChanged(); + } + }; + } + class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { final TextView mSelectName; final ImageView mSelectItemImage; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/AbstractWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/AbstractWidget.java index 9ec0cec5d..211e120c6 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/AbstractWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/AbstractWidget.java @@ -16,8 +16,6 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; -import android.os.Build; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; @@ -26,14 +24,12 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public abstract class AbstractWidget { private static final String LABEL_SUFFIX = "Label"; - protected final Context mContext; protected final View mDefaultFocusView; protected final String mDefaultValue; protected final HyperwalletField mField; @@ -42,16 +38,15 @@ public abstract class AbstractWidget { protected WidgetInputState mWidgetInputState; public AbstractWidget(@Nullable HyperwalletField field, @NonNull WidgetEventListener listener, - @NonNull Context context, @Nullable String defaultValue, @NonNull View defaultFocusView) { + @Nullable String defaultValue, @NonNull View defaultFocusView) { mField = field; mListener = listener; - mContext = context; mDefaultValue = defaultValue; mDefaultFocusView = defaultFocusView; mWidgetInputState = new WidgetInputState(getName()); } - public abstract View getView(); + public abstract View getView(@NonNull final ViewGroup viewGroup); public String getName() { return mField == null ? "" : mField.getName(); @@ -128,17 +123,6 @@ protected void appendLayout(View v, boolean matchParentWidth) { params.addRule(RelativeLayout.BELOW, mBottomViewId); } - int default_margin = (int) (mContext.getResources().getDimension(R.dimen.default_margin) - / mContext.getResources().getDisplayMetrics().density); - int widget_margin_offset = (int) (mContext.getResources().getDimension(R.dimen.widget_left_margin_offset) - / mContext.getResources().getDisplayMetrics().density); - - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { - params.setMargins(default_margin, default_margin, default_margin, default_margin); - } else { - params.setMargins(widget_margin_offset, default_margin, default_margin, default_margin); - } - v.setLayoutParams(params); mBottomViewId = v.getId(); } @@ -148,7 +132,7 @@ protected void setIdFromFieldName(View view) { if (fieldName.isEmpty()) { view.setId(View.generateViewId()); } else { - view.setId(getIdByResourceName(fieldName)); + view.setId(getIdByResourceName(fieldName, view)); } } @@ -157,17 +141,15 @@ protected void setIdFromFieldLabel(View view) { if (fieldName.isEmpty()) { view.setId(View.generateViewId()); } else { - view.setId(getIdByResourceName(fieldName + LABEL_SUFFIX)); + view.setId(getIdByResourceName(fieldName + LABEL_SUFFIX, view)); } } - private int getIdByResourceName(@NonNull final String fieldName) { - int id; - final int idFromResource = mContext.getResources().getIdentifier(fieldName, "id", - mContext.getPackageName()); - // Returns 0 if no such resource was found. - id = idFromResource == 0 ? View.generateViewId() : idFromResource; - return id; + private int getIdByResourceName(@NonNull final String fieldName, @NonNull final View view) { + final int idFromResource = view.getContext().getResources().getIdentifier(fieldName, "id", + view.getContext().getPackageName()); + + return idFromResource == 0 ? View.generateViewId() : idFromResource; } protected class DefaultKeyListener implements View.OnKeyListener { diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java index a3ba9d932..00746d090 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java @@ -16,46 +16,52 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; import android.text.Editable; import android.text.InputType; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public class DateWidget extends AbstractWidget { private ViewGroup mContainer; - private String mValue = ""; + private String mValue; private TextInputLayout mTextInputLayout; - public DateWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @NonNull Context context, + public DateWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); + // input control + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); final EditText editText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + + editText.setEnabled(mField.isEditable()); setIdFromFieldName(editText); + setIdFromFieldLabel(mTextInputLayout); mTextInputLayout.setHint(mField.getLabel()); mTextInputLayout.addView(editText); @@ -88,10 +94,10 @@ public void afterTextChanged(Editable s) { } }); + editText.setText(TextUtils.isEmpty(mDefaultValue) ? mField.getValue() : mDefaultValue); editText.setInputType(InputType.TYPE_CLASS_DATETIME); editText.setOnKeyListener(new DefaultKeyListener(mDefaultFocusView, editText)); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_NEXT); - editText.setText(mDefaultValue); appendLayout(mTextInputLayout, true); mContainer.addView(mTextInputLayout); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java index fc1e66687..9463f308f 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java @@ -2,7 +2,6 @@ import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.IS_DEFAULT_TRANSFER_METHOD; -import android.content.Context; import android.graphics.Typeface; import android.view.View; import android.view.ViewGroup; @@ -21,9 +20,9 @@ public class DefaultAccountWidget extends AbstractWidget { private ViewGroup mContainer; private String mValue; - public DefaultAccountWidget(@NonNull WidgetEventListener listener, @NonNull Context context, + public DefaultAccountWidget(@NonNull WidgetEventListener listener, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(null, listener, context, defaultValue, defaultFocusView); + super(null, listener, defaultValue, defaultFocusView); } @Override @@ -32,26 +31,26 @@ public String getName() { } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); + mContainer = new RelativeLayout(viewGroup.getContext()); // label - TextView label = new TextView(mContext); - label.setText(mContext.getResources().getText(R.string.default_account_label)); + TextView label = new TextView(viewGroup.getContext()); + label.setText(viewGroup.getContext().getResources().getText(R.string.default_account_label)); - label.setTextSize(mContext.getResources().getDimension(R.dimen.font_subtitle2)); + label.setTextSize(viewGroup.getContext().getResources().getDimension(R.dimen.font_subtitle2)); setIdFromFieldLabel(label); label.setTypeface(null, Typeface.BOLD); - label.setTextColor(mContext.getResources().getColor(R.color.colorPrimary)); + label.setTextColor(viewGroup.getContext().getResources().getColor(R.color.colorPrimary)); appendLayout(label, true); mContainer.addView(label); // switch control - Switch toggle = new Switch(mContext); + Switch toggle = new Switch(viewGroup.getContext()); setIdFromFieldName(toggle); - toggle.setText(mContext.getResources().getText(R.string.default_account_sub_label)); - toggle.setTextSize(mContext.getResources().getDimension(R.dimen.font_subtitle2)); + toggle.setText(viewGroup.getContext().getResources().getText(R.string.default_account_sub_label)); + toggle.setTextSize(viewGroup.getContext().getResources().getDimension(R.dimen.font_subtitle2)); if (mDefaultValue == null) { toggle.setChecked(true); // initial state mValue = Boolean.TRUE.toString(); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java index d6f5b00ed..9777f2153 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java @@ -27,43 +27,55 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public class ExpiryDateWidget extends AbstractWidget { private ViewGroup mContainer; private final ExpireDateUtil mExpireDateUtil; private TextInputLayout mTextInputLayout; private String mValue; + private String mMessageInvalidDateLength; + private String mMessageInvalidDate; public ExpiryDateWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, - @NonNull Context context, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + @Nullable String defaultValue, @NonNull View defaultFocusView) { + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; mExpireDateUtil = new ExpireDateUtil(); } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); + + // initialize messaging + mMessageInvalidDateLength = viewGroup.getContext().getResources() + .getString(R.string.error_exact_length_field, MAX_INPUT_LENGTH); + mMessageInvalidDate = viewGroup.getContext().getResources() + .getString(R.string.error_invalid_expiry_date, mField.getLabel()); // input control - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); final EditText editText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + + editText.setEnabled(mField.isEditable()); setIdFromFieldLabel(mTextInputLayout); setIdFromFieldName(editText); editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @@ -75,10 +87,10 @@ public void onFocusChange(View v, boolean hasFocus) { } else { mListener.widgetFocused(ExpiryDateWidget.this.getName()); editText.setHint(editText.getText().toString().trim().isEmpty() ? - mContext.getResources().getString(R.string.api_expiry_date_format) : ""); + viewGroup.getContext().getResources().getString(R.string.api_expiry_date_format) : ""); InputMethodManager imm = (InputMethodManager) - mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + viewGroup.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); } } @@ -170,8 +182,9 @@ public void afterTextChanged(Editable s) { editText.setInputType(InputType.TYPE_CLASS_DATETIME); editText.setHint(mField.getLabel()); - editText.setText(TextUtils.isEmpty(mDefaultValue) ? "" : - mExpireDateUtil.convertDateFromServerFormat(mDefaultValue)); + editText.setText(mExpireDateUtil.convertDateFromServerFormat( + TextUtils.isEmpty(mDefaultValue) ? mField.getValue() : mDefaultValue)); + editText.setOnKeyListener(new DefaultKeyListener(mDefaultFocusView, editText)); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_NEXT); @@ -203,11 +216,11 @@ public String getErrorMessage() { } if (isInvalidLength()) { - return mContext.getResources().getString(R.string.error_exact_length_field, MAX_INPUT_LENGTH); + return mMessageInvalidDateLength; } if (mExpireDateUtil.isInvalidDate(mValue)) { - return mContext.getResources().getString(R.string.error_invalid_expiry_date, mField.getLabel()); + return mMessageInvalidDate; } return null; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java index cafa5e9c2..39dcc7eed 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java @@ -16,45 +16,50 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; import android.text.Editable; import android.text.InputType; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public class NumberWidget extends AbstractWidget { private ViewGroup mContainer; private TextInputLayout mTextInputLayout; - private String mValue = ""; + private String mValue; public NumberWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, - @NonNull Context context, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + @Nullable String defaultValue, @NonNull View defaultFocusView) { + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); + // number input text - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); mTextInputLayout.setHint(mField.getLabel()); + final EditText editText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + editText.setEnabled(mField.isEditable()); setIdFromFieldLabel(mTextInputLayout); setIdFromFieldName(editText); @@ -87,9 +92,9 @@ public void afterTextChanged(Editable s) { } }); + editText.setText(TextUtils.isEmpty(mDefaultValue) ? mField.getValue() : mDefaultValue); editText.setInputType(InputType.TYPE_CLASS_NUMBER); editText.setOnKeyListener(new DefaultKeyListener(mDefaultFocusView, editText)); - editText.setText(mDefaultValue); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_NEXT); mTextInputLayout.addView(editText); appendLayout(mTextInputLayout, true); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java index 7bce341f7..b0d2b8e0f 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java @@ -16,48 +16,54 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; import android.text.Editable; import android.text.InputType; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public class PhoneWidget extends AbstractWidget { private ViewGroup mContainer; private String mValue = ""; private TextInputLayout mTextInputLayout; - public PhoneWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @NonNull Context context, + public PhoneWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); + + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); + // input control final EditText editText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + editText.setEnabled(mField.isEditable()); + mTextInputLayout.addView(editText); mTextInputLayout.setHint(mField.getLabel()); setIdFromFieldName(editText); - + setIdFromFieldLabel(mTextInputLayout); editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { @@ -87,10 +93,10 @@ public void afterTextChanged(Editable s) { } }); + editText.setText(TextUtils.isEmpty(mDefaultValue) ? mField.getValue() : mDefaultValue); editText.setInputType(InputType.TYPE_CLASS_PHONE); editText.setOnKeyListener(new DefaultKeyListener(mDefaultFocusView, editText)); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_NEXT); - editText.setText(mDefaultValue); appendLayout(mTextInputLayout, true); mContainer.addView(mTextInputLayout); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java index a9f34045a..146de1b65 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java @@ -17,15 +17,14 @@ package com.hyperwallet.android.ui.view.widget; import android.app.Activity; -import android.content.Context; import android.text.TextUtils; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -33,11 +32,10 @@ import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; -import com.hyperwallet.android.model.meta.HyperwalletFieldSelectionOption; +import com.hyperwallet.android.model.meta.field.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletFieldSelectionOption; import com.hyperwallet.android.ui.view.WidgetSelectionDialogFragment; -import java.util.Locale; import java.util.Set; import java.util.TreeMap; @@ -50,41 +48,43 @@ public class SelectionWidget extends AbstractWidget implements WidgetSelectionDi private String mValue; public SelectionWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, - @NonNull Context context, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + @Nullable String defaultValue, @NonNull View defaultFocusView) { + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; mSelectionNameValueMap = new TreeMap<>(); - for (HyperwalletFieldSelectionOption option : field.getFieldSelectionOptions()) { - if (!TextUtils.isEmpty(option.getLabel())) { - String label = option.getLabel().substring(1).toLowerCase(Locale.ROOT); - label = option.getLabel().substring(0, 1) + label; - mSelectionNameValueMap.put(label, option.getValue()); + if (field.getFieldSelectionOptions() != null) { + for (HyperwalletFieldSelectionOption option : field.getFieldSelectionOptions()) { + if (!TextUtils.isEmpty(option.getLabel())) { + mSelectionNameValueMap.put(option.getLabel(), option.getValue()); + } } } } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); + setIdFromFieldLabel(mContainer); mContainer.setFocusable(true); mContainer.setFocusableInTouchMode(true); - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); mEditText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); - if (!TextUtils.isEmpty(mDefaultValue)) { - mEditText.setText(getKeyFromValue(mDefaultValue)); - } + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + mEditText.setText( + getKeyFromValue(TextUtils.isEmpty(mDefaultValue) ? mValue = mField.getValue() : mDefaultValue)); setIdFromFieldLabel(mTextInputLayout); setIdFromFieldName(mEditText); mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); mEditText.setKeyListener(null); mEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, - ContextCompat.getDrawable(mContext, R.drawable.ic_keyboard_arrow_down_12dp), null); + ContextCompat.getDrawable(viewGroup.getContext(), R.drawable.ic_keyboard_arrow_down_12dp), null); mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override @@ -104,13 +104,17 @@ public void onFocusChange(View v, boolean hasFocus) { } }); - mEditText.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - hideSoftKey(v); - showSelectionFragmentDialog(); - } - }); + if (mField.isEditable()) { + mEditText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + hideSoftKey(v); + showSelectionFragmentDialog(); + } + }); + } else { + mEditText.setEnabled(false); + } mTextInputLayout.setHint(mField.getLabel()); mTextInputLayout.addView(mEditText); @@ -145,7 +149,8 @@ private void hideSoftKey(@NonNull View focusedView) { private void showSelectionFragmentDialog() { String defaultSelected = TextUtils.isEmpty(mValue) ? - TextUtils.isEmpty(mDefaultValue) ? "" : getKeyFromValue(mDefaultValue) : getKeyFromValue(mValue); + TextUtils.isEmpty(mDefaultValue) ? getKeyFromValue(mField.getValue()) : + getKeyFromValue(mDefaultValue) : getKeyFromValue(mValue); mListener.openWidgetSelectionFragmentDialog(mSelectionNameValueMap, defaultSelected, mField.getLabel(), mField.getName()); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java index fb8e322ec..f16fd51c0 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java @@ -16,46 +16,51 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; import android.text.Editable; import android.text.InputType; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.HyperwalletField; public class TextWidget extends AbstractWidget { private ViewGroup mContainer; - private String mValue = ""; + private String mValue; private TextInputLayout mTextInputLayout; - public TextWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @NonNull Context context, + public TextWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, @Nullable String defaultValue, @NonNull View defaultFocusView) { - super(field, listener, context, defaultValue, defaultFocusView); + super(field, listener, defaultValue, defaultFocusView); mValue = defaultValue; } @Override - public View getView() { + public View getView(@NonNull final ViewGroup viewGroup) { if (mContainer == null) { - mContainer = new RelativeLayout(mContext); + mContainer = (ViewGroup) LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_widget_layout, viewGroup, false); mContainer.setTag(mField.getName()); - mTextInputLayout = new TextInputLayout( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputLayout)); + + mTextInputLayout = new TextInputLayout(new ContextThemeWrapper(viewGroup.getContext(), + mField.isEditable() ? R.style.Widget_Hyperwallet_TextInputLayout + : R.style.Widget_Hyperwallet_TextInputLayout_Disabled)); + final EditText editText = new EditText( - new ContextThemeWrapper(mContext, R.style.Widget_Hyperwallet_TextInputEditText)); - mTextInputLayout.setHint(mField.getLabel()); + new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText)); + editText.setEnabled(mField.isEditable()); + mTextInputLayout.setHint(mField.getLabel()); setIdFromFieldLabel(mTextInputLayout); setIdFromFieldName(editText); editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @@ -87,10 +92,10 @@ public void afterTextChanged(Editable s) { } }); + editText.setText(TextUtils.isEmpty(mDefaultValue) ? mField.getValue() : mDefaultValue); editText.setInputType(InputType.TYPE_CLASS_TEXT); editText.setOnKeyListener(new DefaultKeyListener(mDefaultFocusView, editText)); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_NEXT); - editText.setText(mDefaultValue); mTextInputLayout.addView(editText); appendLayout(mTextInputLayout, true); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/WidgetFactory.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/WidgetFactory.java index 405cd2df9..18bd507ca 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/WidgetFactory.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/WidgetFactory.java @@ -16,22 +16,20 @@ */ package com.hyperwallet.android.ui.view.widget; -import android.content.Context; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.hyperwallet.android.exception.HyperwalletException; -import com.hyperwallet.android.model.meta.EDataType; -import com.hyperwallet.android.model.meta.HyperwalletField; +import com.hyperwallet.android.model.meta.field.EDataType; +import com.hyperwallet.android.model.meta.field.HyperwalletField; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; public class WidgetFactory { - private static final String TAG = AbstractWidget.class.getName(); private static final HashMap WIDGET_MAP_DEFINITION = new HashMap() {{ put(EDataType.TEXT, TextWidget.class); put(EDataType.SELECTION, SelectionWidget.class); @@ -43,18 +41,17 @@ public class WidgetFactory { @SuppressWarnings("unchecked") public static AbstractWidget newWidget(@NonNull HyperwalletField field, @NonNull WidgetEventListener listener, - @NonNull Context context, @Nullable String defaultValue, @NonNull View view) throws HyperwalletException { + @Nullable String defaultValue, @NonNull View view) throws HyperwalletException { try { if (WIDGET_MAP_DEFINITION.containsKey(field.getDataType())) { return (AbstractWidget) WIDGET_MAP_DEFINITION.get(field.getDataType()) - .getConstructor(HyperwalletField.class, WidgetEventListener.class, - Context.class, String.class, View.class) - .newInstance(field, listener, context, defaultValue, view); + .getConstructor(HyperwalletField.class, WidgetEventListener.class, String.class, View.class) + .newInstance(field, listener, defaultValue, view); } } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { throw new HyperwalletException(e); } - return new TextWidget(field, listener, context, defaultValue, view); + return new TextWidget(field, listener, defaultValue, view); } } diff --git a/ui/src/main/res/layout/fragment_add_transfer_method.xml b/ui/src/main/res/layout/fragment_add_transfer_method.xml index d7d00c13d..861e1bdcd 100644 --- a/ui/src/main/res/layout/fragment_add_transfer_method.xml +++ b/ui/src/main/res/layout/fragment_add_transfer_method.xml @@ -36,21 +36,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - + \ No newline at end of file diff --git a/ui/src/main/res/layout/item_widget_section_header.xml b/ui/src/main/res/layout/item_widget_section_header.xml new file mode 100644 index 000000000..10e63e4ab --- /dev/null +++ b/ui/src/main/res/layout/item_widget_section_header.xml @@ -0,0 +1,15 @@ + + + + diff --git a/ui/src/main/res/menu/menu_widget_selection.xml b/ui/src/main/res/menu/menu_widget_selection.xml new file mode 100644 index 000000000..41b5f332e --- /dev/null +++ b/ui/src/main/res/menu/menu_widget_selection.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/ui/src/main/res/values/dimens.xml b/ui/src/main/res/values/dimens.xml index af96abda6..1a3f3fb32 100644 --- a/ui/src/main/res/values/dimens.xml +++ b/ui/src/main/res/values/dimens.xml @@ -47,6 +47,10 @@ 32dp 330dp + + 8dp + 12dp + 136dp 1dp diff --git a/ui/src/main/res/values/ids.xml b/ui/src/main/res/values/ids.xml index df6202824..1fd8a85b2 100644 --- a/ui/src/main/res/values/ids.xml +++ b/ui/src/main/res/values/ids.xml @@ -6,6 +6,12 @@ + + + + + + @@ -14,4 +20,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 7e43ad98f..659d07697 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -14,7 +14,7 @@ Add Account Add Transfer Method Bank Account - Bank Card + Debit Card The length of this field is exactly %d. %s is invalid. @@ -68,11 +68,11 @@ Bank Account - Bank Card - Wire Account + Debit Card + Wire Transfer Paper Check Prepaid Card - PayPal + PayPal Account \uE000 \uE005 @@ -81,9 +81,17 @@ \uE00A \uE021 + Account Holder + Account Information + Address + Contact Information + Identification + Intermediary Account + Search Hint Search Country Search Currency + Search Account Information - %s (%s) Transfer Method Information diff --git a/ui/src/main/res/values/styles.xml b/ui/src/main/res/values/styles.xml index b61828efc..887a6de77 100644 --- a/ui/src/main/res/values/styles.xml +++ b/ui/src/main/res/values/styles.xml @@ -106,6 +106,10 @@ @color/colorSecondaryDark + + + +