diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 0a0a19d2..b34af82c 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825.bin b/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825.bin new file mode 100644 index 00000000..ea58ad44 --- /dev/null +++ b/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825.bin @@ -0,0 +1 @@ +o/SpinnerDatePickerLib-release-runtime diff --git a/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825/SpinnerDatePickerLib-release-runtime/classes.dex b/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825/SpinnerDatePickerLib-release-runtime/classes.dex new file mode 100644 index 00000000..f8d5438f Binary files /dev/null and b/SpinnerDatePickerLib-release/build/.transforms/4647f6ab949e605a829eced215dd9825/SpinnerDatePickerLib-release-runtime/classes.dex differ diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MTextInputMaskedEditText.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MTextInputMaskedEditText.java new file mode 100644 index 00000000..9b9b7c9c --- /dev/null +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MTextInputMaskedEditText.java @@ -0,0 +1,136 @@ +package com.gmeremit.online.gmeremittance_native.common.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.text.InputFilter; +import android.text.InputType; +import android.util.AttributeSet; +import android.util.TypedValue; + +import com.gmeremit.online.gmeremittance_native.R; +import com.gmeremit.online.gmeremittance_native.customwidgets.FontCache; +import com.gmeremit.online.gmeremittance_native.customwidgets.GmeEditText; +import com.gmeremit.online.gmeremittance_native.customwidgets.maskedittext.GmeMaskedEditText; +import com.google.android.material.textfield.TextInputEditText; + +public class MTextInputMaskedEditText extends TextInputEditText { + + + private MaskedTextWatcher maskedTextWatcher; + private int maskingType = 0; + private String prefixText = ""; + private boolean isAlphaNumeric = true; + private GmeMaskedEditText.ValueListener valueListener; + + public MTextInputMaskedEditText(Context context) { + super(context); + init(context, null); + } + + public MTextInputMaskedEditText(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public MTextInputMaskedEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + if (attrs != null) { + + TypedArray a = null; + + try { + a = getContext().obtainStyledAttributes(attrs, R.styleable.MTextInputMaskedEditText); + String fontName = a.getString(R.styleable.MTextInputMaskedEditText_maskedEdTxtFontName); + setTypeface(FontCache.getTypeface(fontName, context)); + + TypedValue outValue = new TypedValue(); + boolean result = a.getValue(R.styleable.GMEMaskedEditText_textType, outValue); + if (result) { + maskingType = outValue.data; + prefixText = a.getString(R.styleable.GMEMaskedEditText_prefixText); + if (prefixText == null) + prefixText = ""; + setupMasking(); + + } + + } catch (Exception e) { + + } finally { + if (a != null) + a.recycle(); + + } + } + } + + public void setMaskingType(int value) { + maskingType = value; + setupMasking(); + } + + private void setupMasking() { + String phoneMask = ""; + switch (maskingType) { + + + case 0: + isAlphaNumeric = true; + setInputType(InputType.TYPE_CLASS_TEXT); + setFilters(new InputFilter[]{new GmeEditText.RegExInputFilter("^[a-zA-Z0-9]+$"), new InputFilter.LengthFilter(50)}); + if (maskedTextWatcher != null) + removeTextChangedListener(maskedTextWatcher); + maskedTextWatcher=null; + break; + + case 1: + if (prefixText.length() > 0) + phoneMask = "-######-#######"; + else + phoneMask = "######-#######"; + isAlphaNumeric = false; + setInputType(InputType.TYPE_CLASS_PHONE); + if (maskedTextWatcher != null) + removeTextChangedListener(maskedTextWatcher); + maskedTextWatcher = new MaskedTextWatcher(phoneMask, prefixText, "#", this, isAlphaNumeric); + addTextChangedListener(maskedTextWatcher); + setFilters(new InputFilter[]{ new InputFilter.LengthFilter(14)}); +// maskedTextWatcher.setValueListener(valueListener); + break; + + case 2: + if (prefixText.length() > 0) + phoneMask = "-####-#####"; + else + phoneMask = "###-####-#####"; + isAlphaNumeric = false; + setInputType(InputType.TYPE_CLASS_PHONE); + if (maskedTextWatcher != null) + removeTextChangedListener(maskedTextWatcher); + maskedTextWatcher = new MaskedTextWatcher(phoneMask, prefixText, "#", this, isAlphaNumeric); + addTextChangedListener(maskedTextWatcher); + setFilters(new InputFilter[]{ new InputFilter.LengthFilter(13)}); + break; + + default: + isAlphaNumeric = true; + setInputType(InputType.TYPE_CLASS_TEXT); + if (maskedTextWatcher != null) + removeTextChangedListener(maskedTextWatcher); + maskedTextWatcher=null; + break; + + } + + } + + + public void setValueListener(ValueListener listener, boolean truncatePrefix) { + maskedTextWatcher.setValueListener(listener,truncatePrefix); + } + +} diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MaskedTextWatcher.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MaskedTextWatcher.java new file mode 100644 index 00000000..dba9ca44 --- /dev/null +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/MaskedTextWatcher.java @@ -0,0 +1,185 @@ +package com.gmeremit.online.gmeremittance_native.common.view; + +import android.text.Editable; +import android.text.TextWatcher; +import android.widget.EditText; +import android.widget.TextView; + +import com.gmeremit.online.gmeremittance_native.customwidgets.maskedittext.GmeMaskedEditText; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class MaskedTextWatcher implements TextWatcher { + + private final String maskString; + private final String prefixText; + private static boolean isAlphaNumeric; + private ValueListener valueListener; + private final Pattern maskPattern; + private final EditText editText; + private boolean shouldTruncatePrefix; + + MaskedTextWatcher(String maskString, String prefixText, String maskSymbol, EditText editText, boolean isAlphaNumeric) { + this.maskString = maskString; + this.prefixText = prefixText; + this.maskPattern = Pattern.compile(maskSymbol); + this.editText = editText; + this.valueListener = null; + this.isAlphaNumeric = isAlphaNumeric; + } + + public void setValueListener(ValueListener listener,boolean shouldTruncatePrefix) { + this.valueListener = listener; + this.shouldTruncatePrefix=shouldTruncatePrefix; + } + + private String result = ""; + private EditState state = EditState.IDLE; + private Integer cursorPosition; + private Integer cursorShifting; + + private String phoneString = ""; + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (state == EditState.IDLE) { + cursorShifting = s.length(); + } + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + + @Override + public void afterTextChanged(Editable s) { + final String value = s.toString(); + if (state == EditState.RELEASE) { + cursorShifting = s.length() - cursorShifting; + cursorPosition = cursorPosition + cursorShifting; + if (cursorShifting > 0) { + if (cursorPosition < value.length()) { + cursorPosition--; + if (isAlphaNumeric && !Character.isLetterOrDigit(value.charAt(cursorPosition))) { + cursorPosition++; + } + if (!isAlphaNumeric && !Character.isDigit(value.charAt(cursorPosition))) { + cursorPosition++; + } + } + + } else { + cursorPosition++; + } + + editText.setSelection(Math.max(0, Math.min(cursorPosition, value.length()))); + + state = EditState.IDLE; + return; + } + + if (state == EditState.IDLE) { + if (s.toString().isEmpty()) { + phoneString = ""; + cursorPosition = 0; + return; + } + + cursorPosition = editText.getSelectionStart(); + + String rawString = value.replace(prefixText, ""); + //Raw string contains the character input from user. + rawString = getRegExPattern().matcher(rawString).replaceAll(""); + Queue charsQueue = new LinkedList<>(); + for (char c : rawString.toCharArray()) { + charsQueue.add(c); + } + + //Build masked text for display. + StringBuilder rawMaskBuilder = new StringBuilder(prefixText + maskString); + Matcher matcher = maskPattern.matcher(prefixText + maskString); + while (matcher.find()) { + int start = matcher.start(); + if (!charsQueue.isEmpty()) { + rawMaskBuilder.replace(start, start + 1, charsQueue.poll().toString()); + if (charsQueue.isEmpty()) { + result = rawMaskBuilder.substring(0, start + 1); + break; + } + } else { + result = rawMaskBuilder.substring(0, start); + break; + } + } + + //Prepare to send to the listener the raw data that user has entered. + String data = getRegExPattern().matcher(rawMaskBuilder.toString()).replaceAll(""); + + if (valueListener != null) { + if (prefixText.length() > 0) { + if(shouldTruncatePrefix) + valueListener.onValueChanged(data.substring(prefixText.length() - 1)); + else + valueListener.onValueChanged(data); + } + else + valueListener.onValueChanged(data); + } + state = EditState.EDIT; + } + + switch (state) { + case EDIT: + state = EditState.CLEAR; + s.clear(); + break; + case CLEAR: + state = EditState.RELEASE; + s.append(result, 0, result.length()); + break; + default: + break; + } + } + + + /** + * Experimental. + * + * @param editText + * @param mask + */ + @Deprecated + public static void validatePresetup(TextView editText, String mask) { + //Check setOnFocusChangeListener + if (editText.getOnFocusChangeListener() != null) { + throw new RuntimeException("If you wanna to use OnFocusChangeListener add it through withOnFocusChangeListener() method"); + } + //Check maskString + if (mask == null) { + throw new RuntimeException("Mask can't be null"); + } + + } + + private static Pattern getRegExPattern() { + if (MaskedTextWatcher.isAlphaNumeric) + return Pattern.compile("[^[a-zA-Z0-9]*$]"); + else + return Pattern.compile("[^\\d]+"); + + } + + public String getPhone() { + return phoneString; + } + + enum EditState { + IDLE, EDIT, CLEAR, RELEASE + } +} diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/ValueListener.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/ValueListener.java new file mode 100644 index 00000000..a06a93d6 --- /dev/null +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/common/view/ValueListener.java @@ -0,0 +1,5 @@ +package com.gmeremit.online.gmeremittance_native.common.view; + +public interface ValueListener { + void onValueChanged(String value); +} diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/maskedittext/MaskedTextWatcher.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/maskedittext/MaskedTextWatcher.java index 6ae970a8..ac9c1f29 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/maskedittext/MaskedTextWatcher.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/maskedittext/MaskedTextWatcher.java @@ -10,7 +10,7 @@ import java.util.Queue; import java.util.regex.Matcher; import java.util.regex.Pattern; -class MaskedTextWatcher implements TextWatcher { + class MaskedTextWatcher implements TextWatcher { private final String maskString; private final String prefixText; @@ -20,7 +20,7 @@ class MaskedTextWatcher implements TextWatcher { private final EditText editText; private boolean shouldTruncatePrefix; - MaskedTextWatcher(String maskString, String prefixText, String maskSymbol, EditText editText, boolean isAlphaNumeric) { + MaskedTextWatcher(String maskString, String prefixText, String maskSymbol, EditText editText, boolean isAlphaNumeric) { this.maskString = maskString; this.prefixText = prefixText; this.maskPattern = Pattern.compile(maskSymbol); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/kycV3/view/personal/CustomerDetailFragment.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/kycV3/view/personal/CustomerDetailFragment.java index 663b6d05..320bb201 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/kycV3/view/personal/CustomerDetailFragment.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/kycV3/view/personal/CustomerDetailFragment.java @@ -8,6 +8,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; @@ -22,6 +23,7 @@ import androidx.transition.TransitionManager; import com.gmeremit.online.gmeremittance_native.R; import com.gmeremit.online.gmeremittance_native.base.BaseFragment; +import com.gmeremit.online.gmeremittance_native.common.view.MTextInputMaskedEditText; import com.gmeremit.online.gmeremittance_native.customwidgets.GmeEditText; import com.gmeremit.online.gmeremittance_native.customwidgets.common.GenericImageWithTextListingDialog; import com.gmeremit.online.gmeremittance_native.customwidgets.common.GenericTextListingDialog; @@ -33,6 +35,7 @@ import com.gmeremit.online.gmeremittance_native.kycV3.presenter.KYCV3ViewModel; import com.gmeremit.online.gmeremittance_native.utils.RxUtils; import com.gmeremit.online.gmeremittance_native.utils.Utils; import com.gmeremit.online.gmeremittance_native.utils.other.Utility; +import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import com.jakewharton.rxbinding3.widget.RxTextView; import com.tsongkha.spinnerdatepicker.SpinnerDatePickerDialogBuilder; @@ -78,17 +81,17 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present //Form 1 @BindView(R.id.ed_firstname) - EditText ed_firstname; + TextInputEditText ed_firstname; @BindView(R.id.firstnameWrapper) TextInputLayout fullNameWrapper; @BindView(R.id.ed_gender) - EditText ed_gender; + AutoCompleteTextView ed_gender; @BindView(R.id.genderListWrapper) TextInputLayout genderListWrapper; @BindView(R.id.ed_dob) - EditText ed_dob; + AutoCompleteTextView ed_dob; @BindView(R.id.dobWrapper) TextInputLayout dobWrapper; @@ -98,12 +101,12 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present TextInputLayout emailWrapper; @BindView(R.id.ed_city) - EditText ed_city; + AutoCompleteTextView ed_city; @BindView(R.id.cityWrapper) TextInputLayout cityWrapper; @BindView(R.id.ed_occupation) - EditText ed_occupation; + AutoCompleteTextView ed_occupation; @BindView(R.id.occupationSelectionWrapper) TextInputLayout occupationSelectionWrapper; @@ -114,7 +117,7 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present //Form 2 @BindView(R.id.ed_primaryBank) - EditText ed_primaryBank; + AutoCompleteTextView ed_primaryBank; @BindView(R.id.primaryBankListWrapper) TextInputLayout primaryBankListWrapper; @@ -127,7 +130,7 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present TextView txt_passport_label; @BindView(R.id.ed_passportId) - EditText ed_passportId; + MTextInputMaskedEditText ed_passportId; @BindView(R.id.passportIdWrapper) TextInputLayout passportIdWrapper; @@ -135,15 +138,13 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present EditText ed_passportIdIssueDate; @BindView(R.id.passportIdIssueDateWrapper) TextInputLayout passportIdIssueDateWrapper; - @BindView(R.id.passportIdIssueDateContainer) - View passportIdIssueDateContainer; + @BindView(R.id.ed_passportIdExpiryDate) - EditText ed_passportIdExpiryDate; + AutoCompleteTextView ed_passportIdExpiryDate; @BindView(R.id.passportIdExpiryDateWrapper) TextInputLayout passportIdExpiryDateWrapper; - @BindView(R.id.passportIdExpiryDateContainer) - View passportIdExpiryDateContainer; + @BindView(R.id.txt_another_id_label) @@ -153,32 +154,30 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present TextView txt_another_id_clear; @BindView(R.id.ed_idType) - EditText ed_idType; + AutoCompleteTextView ed_idType; @BindView(R.id.idTypeWrapper) TextInputLayout idTypeWrapper; @BindView(R.id.ed_anotherId) - GmeMaskedEditText ed_anotherId; + MTextInputMaskedEditText ed_anotherId; @BindView(R.id.anotherIdWrapper) TextInputLayout anotherIdWrapper; @BindView(R.id.ed_anotherIssueDate) - EditText ed_anotherIssueDate; + AutoCompleteTextView ed_anotherIssueDate; @BindView(R.id.anotherIssueDateWrapper) TextInputLayout anotherIssueDateWrapper; - @BindView(R.id.anotherIdIssueDateContainer) - View anotherIdIssueDateContainer; + @BindView(R.id.ed_anotherExpiryDate) - EditText ed_anotherExpiryDate; + AutoCompleteTextView ed_anotherExpiryDate; @BindView(R.id.anotherExpiryDateWrapper) TextInputLayout anotherExpiryDateWrapper; - @BindView(R.id.anotherIdExpiryDateContainer) - View anotherIdExpiryDateContainer; + @BindView(R.id.ed_branch) - EditText ed_branch; + AutoCompleteTextView ed_branch; @BindView(R.id.branchSelectionWrapper) TextInputLayout branchSelectionWrapper; @@ -340,16 +339,16 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present kycv3ViewModel.getAlternateIdIssueDateRequireLiveData().observe(getViewLifecycleOwner(), action -> { if (action) - anotherIdIssueDateContainer.setVisibility(View.VISIBLE); + anotherIssueDateWrapper.setVisibility(View.VISIBLE); else - anotherIdIssueDateContainer.setVisibility(GONE); + anotherIssueDateWrapper.setVisibility(GONE); }); kycv3ViewModel.getAlternateIdExpiryDateRequireLiveData().observe(getViewLifecycleOwner(), action -> { if (action) - anotherIdExpiryDateContainer.setVisibility(View.VISIBLE); + anotherExpiryDateWrapper.setVisibility(View.VISIBLE); else - anotherIdExpiryDateContainer.setVisibility(GONE); + anotherExpiryDateWrapper.setVisibility(GONE); }); @@ -380,16 +379,16 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present if (action) { txt_passport_label.setVisibility(GONE); passportIdWrapper.setVisibility(GONE); - passportIdExpiryDateContainer.setVisibility(GONE); - passportIdIssueDateContainer.setVisibility(GONE); + passportIdExpiryDateWrapper.setVisibility(GONE); + passportIdIssueDateWrapper.setVisibility(GONE); txt_another_id_clear.setVisibility(View.GONE); txt_another_id_label.setText(getString(R.string.id_type_text)); } else { txt_passport_label.setVisibility(View.VISIBLE); passportIdWrapper.setVisibility(View.VISIBLE); - passportIdExpiryDateContainer.setVisibility(View.VISIBLE); - passportIdIssueDateContainer.setVisibility(View.VISIBLE); + passportIdExpiryDateWrapper.setVisibility(View.VISIBLE); + passportIdIssueDateWrapper.setVisibility(View.VISIBLE); txt_another_id_clear.setVisibility(View.VISIBLE); txt_another_id_label.setText(getString(R.string.another_id_information_text)); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java index 012329a8..55c2ac9d 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java @@ -80,7 +80,7 @@ public class LoginV2Presenter extends BaseViewModel implements LoginV2PresenterI private void mockValidUserLogin() { loginViewLiveData.setPasswordInputLiveData(new FormInputStateDTO<>(true,null,"123456")); - loginViewLiveData.setUserIdInputLiveData(new FormInputStateDTO<>(true,null,"timmy")); + loginViewLiveData.setUserIdInputLiveData(new FormInputStateDTO<>(true,null,"bamboo")); } private void bindView(LoginViewLiveData.LoginViewBindings viewBindings) { diff --git a/app/src/main/res/color/textinput_hint_color.xml b/app/src/main/res/color/textinput_hint_color.xml new file mode 100644 index 00000000..ba0eb2b2 --- /dev/null +++ b/app/src/main/res/color/textinput_hint_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_kyc_customer_detail.xml b/app/src/main/res/layout/fragment_kyc_customer_detail.xml index fc1a2f9c..646f57f2 100644 --- a/app/src/main/res/layout/fragment_kyc_customer_detail.xml +++ b/app/src/main/res/layout/fragment_kyc_customer_detail.xml @@ -39,201 +39,107 @@ app:txtfontName="@string/semibold" /> - - - - - - - + - - - + style="@style/MAutoCompleteDropDown" /> - - + - - - - - + - - + - + + + - - - + + + style="@style/MTextInputLayoutFormDropDown" + app:endIconMode="dropdown_menu" + app:errorEnabled="true"> - + style="@style/MAutoCompleteDropDown" /> - - - - - + /> + - - - - + /> + - - -