Skip to content

Commit

Permalink
Add setter for custom CVC field label on CardMultilineWidget (#843)
Browse files Browse the repository at this point in the history
Fixes #838
  • Loading branch information
mshafrir-stripe authored Apr 1, 2019
1 parent 6b9bbc0 commit e6fbadc
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,33 @@ public class CardMultilineWidget extends LinearLayout {
private boolean mIsEnabled;
private boolean mShouldShowPostalCode;
private boolean mHasAdjustedDrawable;
@Nullable private String mCustomCvcLabel;

private @Card.CardBrand String mCardBrand;
private @ColorInt int mTintColorInt;

public CardMultilineWidget(Context context) {
super(context);
initView(null);
public CardMultilineWidget(@NonNull Context context) {
this(context, null);
}

public CardMultilineWidget(Context context, AttributeSet attrs) {
super(context, attrs);
initView(attrs);
public CardMultilineWidget(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public CardMultilineWidget(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
public CardMultilineWidget(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
this(context, attrs, defStyleAttr, false);
}

@VisibleForTesting
CardMultilineWidget(Context context, boolean shouldShowPostalCode) {
super(context);
mShouldShowPostalCode = shouldShowPostalCode;
initView(null);
CardMultilineWidget(@NonNull Context context, boolean shouldShowPostalCode) {
this(context, null, 0, shouldShowPostalCode);
}

private CardMultilineWidget(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, boolean shouldShowPostalCode) {
super(context, attrs, defStyleAttr);
initView(attrs, shouldShowPostalCode);
}

/**
Expand Down Expand Up @@ -170,6 +173,14 @@ public void onWindowFocusChanged(boolean hasWindowFocus) {
}
}

/**
* Set an optional CVC field label to override defaults. Set to `null` to use defaults.
*/
public void setCvcLabel(@Nullable String cvcLabel) {
mCustomCvcLabel = cvcLabel;
updateCvc();
}

public void setShouldShowPostalCode(boolean shouldShowPostalCode) {
mShouldShowPostalCode = shouldShowPostalCode;
adjustViewForPostalCodeAttribute();
Expand Down Expand Up @@ -338,7 +349,9 @@ private int getDynamicBufferInPixels() {
return pixels.intValue();
}

private void initView(AttributeSet attrs) {
private void initView(@Nullable AttributeSet attrs, boolean shouldShowPostalCode) {
mShouldShowPostalCode = shouldShowPostalCode;

setOrientation(VERTICAL);
inflate(getContext(), R.layout.card_multiline_widget, this);

Expand Down Expand Up @@ -500,8 +513,7 @@ public void onFocusChange(View v, boolean hasFocus) {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
flipToCvcIconIfNotFinished();
@StringRes int helperText = getCvcHelperText();
mCvcEditText.setHintDelayed(helperText, COMMON_HINT_DELAY);
mCvcEditText.setHintDelayed(getCvcHelperText(), COMMON_HINT_DELAY);
if (mCardInputListener != null) {
mCardInputListener.onFocusChange(FOCUS_CVC);
}
Expand Down Expand Up @@ -551,23 +563,25 @@ private void initTextInputLayoutErrorHandlers(

private void updateBrand(@NonNull @Card.CardBrand String brand) {
mCardBrand = brand;
updateCvc(mCardBrand);
updateCvc();
updateDrawable(BRAND_RESOURCE_MAP.get(brand), Card.UNKNOWN.equals(brand));
}

private void updateCvc(@NonNull @Card.CardBrand String brand) {
if (Card.AMERICAN_EXPRESS.equals(brand)) {
mCvcEditText.setFilters(
new InputFilter[]{
new InputFilter.LengthFilter(Card.CVC_LENGTH_AMERICAN_EXPRESS)
});
mCvcTextInputLayout.setHint(getResources().getString(R.string.cvc_amex_hint));
} else {
mCvcEditText.setFilters(
new InputFilter[]{
new InputFilter.LengthFilter(Card.CVC_LENGTH_COMMON)});
mCvcTextInputLayout.setHint(getResources().getString(R.string.cvc_number_hint));
private void updateCvc() {
final int maxLength = Card.AMERICAN_EXPRESS.equals(mCardBrand) ?
Card.CVC_LENGTH_AMERICAN_EXPRESS : Card.CVC_LENGTH_COMMON;
mCvcEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
mCvcTextInputLayout.setHint(getCvcLabel());
}

@NonNull
private String getCvcLabel() {
if (mCustomCvcLabel != null) {
return mCustomCvcLabel;
}

return getResources().getString(Card.AMERICAN_EXPRESS.equals(mCardBrand) ?
R.string.cvc_amex_hint : R.string.cvc_number_hint);
}

private void updateDrawable(@DrawableRes int iconResourceId, boolean needsTint) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private void setUpForLocalTest() {
mActivityController = Robolectric.buildActivity(AddSourceActivity.class)
.create().start().resume().visible();
final AddSourceActivity addSourceActivity = mActivityController.get();
mCardMultilineWidget =addSourceActivity.findViewById(R.id.add_source_card_entry_widget);
mCardMultilineWidget = addSourceActivity.findViewById(R.id.add_source_card_entry_widget);
mProgressBar = addSourceActivity.findViewById(R.id.progress_bar_as);
mWidgetControlGroup = new CardMultilineWidgetTest.WidgetControlGroup(mCardMultilineWidget);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,15 @@ public void clear_whenFieldsInErrorState_clearsFieldsAndHidesErrors() {
assertFalse(mFullGroup.postalCodeEditText.getShouldShowError());
}

@Test
public void setCvcLabel_shouldShowCustomLabelIfPresent() {
mCardMultilineWidget.setCvcLabel("my cool cvc");
assertEquals("my cool cvc", mFullGroup.cvcEditText.getHint());

mCardMultilineWidget.setCvcLabel(null);
assertEquals("CVC", mFullGroup.cvcEditText.getHint());
}

@Test
public void initView_whenZipRequiredThenSetToHidden_secondRowLosesPostalCodeAndAdjustsMargin() {
assertEquals(View.VISIBLE, mFullGroup.postalCodeInputLayout.getVisibility());
Expand Down Expand Up @@ -555,16 +564,15 @@ public void setEnabled_setsEnabledPropertyOnAllChildWidgets() {
}

static class WidgetControlGroup {

CardNumberEditText cardNumberEditText;
TextInputLayout cardInputLayout;
ExpiryDateEditText expiryDateEditText;
TextInputLayout expiryInputLayout;
StripeEditText cvcEditText;
TextInputLayout cvcInputLayout;
StripeEditText postalCodeEditText;
TextInputLayout postalCodeInputLayout;
LinearLayout secondRowLayout;
@NonNull final CardNumberEditText cardNumberEditText;
@NonNull final TextInputLayout cardInputLayout;
@NonNull final ExpiryDateEditText expiryDateEditText;
@NonNull final TextInputLayout expiryInputLayout;
@NonNull final StripeEditText cvcEditText;
@NonNull final TextInputLayout cvcInputLayout;
@NonNull final StripeEditText postalCodeEditText;
@NonNull final TextInputLayout postalCodeInputLayout;
@NonNull final LinearLayout secondRowLayout;

WidgetControlGroup(@NonNull CardMultilineWidget parentWidget) {
cardNumberEditText = parentWidget.findViewById(R.id.et_add_source_card_number_ml);
Expand Down

0 comments on commit e6fbadc

Please sign in to comment.