- Changes in validators, now every fieldvalidator take charge of its own validation

- Added the board activity and the view pager with balance, transactions and contacts.
This commit is contained in:
Javier Varona 2017-10-07 23:03:59 -04:00
parent 28e39c8b25
commit 2042c37afa
22 changed files with 559 additions and 192 deletions

View file

@ -32,23 +32,22 @@ dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:3.0.1', { androidTestCompile('com.android.support.test.espresso:espresso-core:3.0.1', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
//testCompile 'com.android.support.test:runner:1.0.1'
compile 'com.android.support:appcompat-v7:26.1.0' compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:support-v4:26.1.0' compile 'com.android.support:support-v4:26.1.0'
compile 'com.android.support:design:26.1.0' compile 'com.android.support:design:26.1.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12' compile 'android.arch.lifecycle:runtime:1.0.0-alpha9-1'
testCompile 'org.mockito:mockito-core:1.10.19' compile 'android.arch.lifecycle:extensions:1.0.0-alpha9-1'
//testCompile 'com.android.support.test:runner:1.0.1' compile 'android.arch.persistence.room:runtime:1.0.0-alpha9-1'
compile 'android.arch.paging:runtime:1.0.0-alpha1'
compile "android.arch.lifecycle:runtime:1.0.0-alpha9-1" compile 'com.idescout.sql:sqlscout-server:2.0'
compile "android.arch.lifecycle:extensions:1.0.0-alpha9-1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha9-1"
compile 'android.arch.persistence.room:runtime:1.0.0-alpha9-1';
apt "android.arch.persistence.room:compiler:1.0.0-alpha9-1";
compile "android.arch.paging:runtime:1.0.0-alpha1";
compile 'com.idescout.sql:sqlscout-server:2.0';
compile 'com.google.code.gson:gson:2.2.4' compile 'com.google.code.gson:gson:2.2.4'
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
@ -56,7 +55,10 @@ dependencies {
compile 'com.neovisionaries:nv-websocket-client:1.30' compile 'com.neovisionaries:nv-websocket-client:1.30'
compile 'org.tukaani:xz:1.6' compile 'org.tukaani:xz:1.6'
compile 'com.jakewharton:butterknife:8.8.1' compile 'com.jakewharton:butterknife:8.8.1'
apt 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'com.github.bilthon:graphenej:0.4.5' compile 'com.github.bilthon:graphenej:0.4.5'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0-alpha9-1'
apt 'android.arch.persistence.room:compiler:1.0.0-alpha9-1'
apt 'com.jakewharton:butterknife-compiler:8.8.1'
} }

View file

@ -19,6 +19,8 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".activities.BoardActivity" >
</activity>
<activity android:name=".activities.AccountSeedsManagementActivity" > <activity android:name=".activities.AccountSeedsManagementActivity" >
</activity> </activity>
<activity android:name=".activities.ImportSeedActivity" > <activity android:name=".activities.ImportSeedActivity" >

View file

@ -0,0 +1,64 @@
package cy.agorise.crystalwallet.activities;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.fragments.BalanceFragment;
import cy.agorise.crystalwallet.fragments.ContactsFragment;
import cy.agorise.crystalwallet.fragments.TransactionsFragment;
/**
* Created by Henry Varona on 7/10/2017.
*/
public class BoardActivity extends AppCompatActivity {
@BindView(R.id.pager)
public ViewPager mPager;
public BoardPagerAdapter boardAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.board);
ButterKnife.bind(this);
boardAdapter = new BoardPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(boardAdapter);
}
private class BoardPagerAdapter extends FragmentStatePagerAdapter {
public BoardPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new BalanceFragment();
case 1:
return new TransactionsFragment();
case 2:
return new ContactsFragment();
}
return null; //new OnConstructionFragment();
}
@Override
public int getCount() {
return 3;
}
}
}

View file

@ -1,17 +1,12 @@
package cy.agorise.crystalwallet.activities; package cy.agorise.crystalwallet.activities;
import android.arch.lifecycle.LifecycleActivity;
import android.arch.lifecycle.ViewModelProviders; import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.text.Editable; import android.text.Editable;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
@ -19,15 +14,12 @@ import butterknife.OnClick;
import butterknife.OnTextChanged; import butterknife.OnTextChanged;
import cy.agorise.crystalwallet.R; import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.models.AccountSeed; import cy.agorise.crystalwallet.models.AccountSeed;
import cy.agorise.crystalwallet.viewmodels.AccountSeedListViewModel;
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel; import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel;
import cy.agorise.crystalwallet.viewmodels.validators.ImportSeedValidator; import cy.agorise.crystalwallet.viewmodels.validators.ImportSeedValidator;
import cy.agorise.crystalwallet.viewmodels.validators.ImportSeedValidatorListener; import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener;
import cy.agorise.crystalwallet.viewmodels.validators.ValidationField; import cy.agorise.crystalwallet.viewmodels.validators.ValidationField;
import cy.agorise.crystalwallet.views.TransactionListView;
public class ImportSeedActivity extends AppCompatActivity implements ImportSeedValidatorListener { public class ImportSeedActivity extends AppCompatActivity implements UIValidatorListener {
AccountSeedViewModel accountSeedViewModel; AccountSeedViewModel accountSeedViewModel;
ImportSeedValidator importSeedValidator; ImportSeedValidator importSeedValidator;
@ -60,29 +52,28 @@ public class ImportSeedActivity extends AppCompatActivity implements ImportSeedV
ButterKnife.bind(this); ButterKnife.bind(this);
btnImport.setEnabled(false);
accountSeedViewModel = ViewModelProviders.of(this).get(AccountSeedViewModel.class); accountSeedViewModel = ViewModelProviders.of(this).get(AccountSeedViewModel.class);
importSeedValidator = accountSeedViewModel.getValidator(); importSeedValidator = new ImportSeedValidator(this.getApplicationContext(),etPin,etPinConfirmation,etAccountName,etSeedWords);
importSeedValidator.setListener(this); importSeedValidator.setListener(this);
} }
@OnTextChanged(value = R.id.etPin, @OnTextChanged(value = R.id.etPin,
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
void afterPinChanged(Editable editable) { void afterPinChanged(Editable editable) {
this.importSeedValidator.validatePin(editable.toString()); this.importSeedValidator.validate();
this.importSeedValidator.validatePinConfirmation(etPinConfirmation.getText().toString(),editable.toString());
} }
@OnTextChanged(value = R.id.etPinConfirmation, @OnTextChanged(value = R.id.etPinConfirmation,
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
void afterPinConfirmationChanged(Editable editable) { void afterPinConfirmationChanged(Editable editable) {
this.importSeedValidator.validatePinConfirmation(editable.toString(), etPin.getText().toString()); this.importSeedValidator.validate();
} }
@OnTextChanged(value = R.id.etAccountName, @OnTextChanged(value = R.id.etAccountName,
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
void afterAccountNameChanged(Editable editable) { void afterAccountNameChanged(Editable editable) {
this.importSeedValidator.validateAccountName(editable.toString(), etSeedWords.getText().toString()); this.importSeedValidator.validate();
} }
@OnClick(R.id.btnImport) @OnClick(R.id.btnImport)
@ -103,31 +94,27 @@ public class ImportSeedActivity extends AppCompatActivity implements ImportSeedV
@Override @Override
public void onValidationSucceeded(ValidationField field) { public void onValidationSucceeded(ValidationField field) {
switch (field.getName()){ if (field.getView() == etPin) {
case "pin":
tvPinError.setText(""); tvPinError.setText("");
break; } else if (field.getView() == etPinConfirmation){
case "pinconfirmation":
tvPinConfirmationError.setText(""); tvPinConfirmationError.setText("");
break; } else if (field.getView() == etAccountName){
case "accountname":
tvAccountNameError.setText(""); tvAccountNameError.setText("");
break; }
if (this.importSeedValidator.isValid()){
btnImport.setEnabled(true);
} }
} }
@Override @Override
public void onValidationFailed(ValidationField field) { public void onValidationFailed(ValidationField field) {
switch (field.getName()){ if (field.getView() == etPin) {
case "pin":
tvPinError.setText(field.getMessage()); tvPinError.setText(field.getMessage());
break; } else if (field.getView() == etPinConfirmation){
case "pinconfirmation":
tvPinConfirmationError.setText(field.getMessage()); tvPinConfirmationError.setText(field.getMessage());
break; } else if (field.getView() == etAccountName){
case "accountname":
tvAccountNameError.setText(field.getMessage()); tvAccountNameError.setText(field.getMessage());
break;
} }
} }
} }

View file

@ -42,12 +42,15 @@ public class IntroActivity extends AppCompatActivity {
//Checks if the user has any seed created //Checks if the user has any seed created
AccountSeedListViewModel accountSeedListViewModel = ViewModelProviders.of(this).get(AccountSeedListViewModel.class); AccountSeedListViewModel accountSeedListViewModel = ViewModelProviders.of(this).get(AccountSeedListViewModel.class);
//if (accountSeedListViewModel.accountSeedsCount() == 0){ if (accountSeedListViewModel.accountSeedsCount() == 0){
//If the user doesn't have any seeds created, then //If the user doesn't have any seeds created, then
//send the user to create/import an account //send the user to create/import an account
Intent intent = new Intent(this, AccountSeedsManagementActivity.class); Intent intent = new Intent(this, AccountSeedsManagementActivity.class);
startActivity(intent); startActivity(intent);
//} } else {
Intent intent = new Intent(this, BoardActivity.class);
startActivity(intent);
}
/*CrystalDatabase db = CrystalDatabase.getAppDatabase(getApplicationContext()); /*CrystalDatabase db = CrystalDatabase.getAppDatabase(getApplicationContext());
List<AccountSeed> seeds = RandomSeedGenerator.generateSeeds(2); List<AccountSeed> seeds = RandomSeedGenerator.generateSeeds(2);

View file

@ -0,0 +1,36 @@
package cy.agorise.crystalwallet.fragments;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cy.agorise.crystalwallet.R;
public class BalanceFragment extends Fragment {
public BalanceFragment() {
// Required empty public constructor
}
public static BalanceFragment newInstance() {
BalanceFragment fragment = new BalanceFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_balance, container, false);
}
}

View file

@ -0,0 +1,34 @@
package cy.agorise.crystalwallet.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cy.agorise.crystalwallet.R;
public class ContactsFragment extends Fragment {
public ContactsFragment() {
// Required empty public constructor
}
public static ContactsFragment newInstance() {
ContactsFragment fragment = new ContactsFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_contacts, container, false);
}
}

View file

@ -0,0 +1,34 @@
package cy.agorise.crystalwallet.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cy.agorise.crystalwallet.R;
public class TransactionsFragment extends Fragment {
public TransactionsFragment() {
// Required empty public constructor
}
public static TransactionsFragment newInstance() {
TransactionsFragment fragment = new TransactionsFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_transactions, container, false);
}
}

View file

@ -21,7 +21,6 @@ public class AccountSeedViewModel extends AndroidViewModel {
private LiveData<AccountSeed> accountSeed; private LiveData<AccountSeed> accountSeed;
private CrystalDatabase db; private CrystalDatabase db;
private ImportSeedValidator importSeedValidator;
private Application app; private Application app;
public AccountSeedViewModel(Application application) { public AccountSeedViewModel(Application application) {
@ -34,14 +33,6 @@ public class AccountSeedViewModel extends AndroidViewModel {
this.accountSeed = this.db.accountSeedDao().findById(seedId); this.accountSeed = this.db.accountSeedDao().findById(seedId);
} }
public ImportSeedValidator getValidator(){
if (this.importSeedValidator == null){
this.importSeedValidator = new ImportSeedValidator(this.app.getResources());
}
return this.importSeedValidator;
}
public void addSeed(AccountSeed seed){ public void addSeed(AccountSeed seed){
this.db.accountSeedDao().insertAccountSeed(seed); this.db.accountSeedDao().insertAccountSeed(seed);
} }
@ -50,17 +41,4 @@ public class AccountSeedViewModel extends AndroidViewModel {
return this.accountSeed; return this.accountSeed;
} }
public void validateAccountSeed(){
if (this.accountSeed != null){
AccountSeed seed = this.accountSeed.getValue();
ValidateImportBitsharesAccountRequest request = new ValidateImportBitsharesAccountRequest(seed.getName(),seed.getMasterSeed());
request.setListener(new CryptoNetInfoRequestListener() {
@Override
public void onCarryOut() {
}
});
}
}
} }

View file

@ -0,0 +1,50 @@
package cy.agorise.crystalwallet.viewmodels.validators;
import android.widget.EditText;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListener;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests;
import cy.agorise.crystalwallet.cryptonetinforequests.ValidateImportBitsharesAccountRequest;
/**
* Created by Henry Varona on 7/10/2017.
*/
public class BitsharesAccountMnemonicValidationField extends ValidationField {
private EditText mnemonicField;
private EditText accountNameField;
public BitsharesAccountMnemonicValidationField(EditText mnemonicField, EditText accountNameField){
super(mnemonicField);
this.mnemonicField = mnemonicField;
this.accountNameField = accountNameField;
}
public void validate(){
final String newMnemonicValue = mnemonicField.getText().toString();
final String newAccountNameValue = accountNameField.getText().toString();
final String mixedValue = newMnemonicValue+"_"+newAccountNameValue;
this.setLastValue(mixedValue);
this.startValidating();
final ValidationField field = this;
final ValidateImportBitsharesAccountRequest request = new ValidateImportBitsharesAccountRequest(newAccountNameValue,newMnemonicValue);
request.setListener(new CryptoNetInfoRequestListener() {
@Override
public void onCarryOut() {
if (!request.getMnemonicIsCorrect()){
setValidForValue(mixedValue, false);
setMessage(validator.getContext().getResources().getString(R.string.account_name_not_exist));
validator.validationFailed(field);
} else {
setValidForValue(mixedValue, true);
validator.validationSucceeded(field);
}
}
});
CryptoNetInfoRequests.getInstance().addRequest(request);
}
}

View file

@ -0,0 +1,46 @@
package cy.agorise.crystalwallet.viewmodels.validators;
import android.content.Context;
import android.widget.EditText;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListener;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests;
import cy.agorise.crystalwallet.cryptonetinforequests.ValidateImportBitsharesAccountRequest;
/**
* Created by Henry Varona on 7/10/2017.
*/
public class BitsharesAccountNameValidationField extends ValidationField {
private EditText accountNameField;
public BitsharesAccountNameValidationField(EditText accountNameField){
super(accountNameField);
this.accountNameField = accountNameField;
}
public void validate(){
final String newValue = accountNameField.getText().toString();
this.setLastValue(newValue);
this.startValidating();
final ValidationField field = this;
final ValidateImportBitsharesAccountRequest request = new ValidateImportBitsharesAccountRequest(newValue,"");
request.setListener(new CryptoNetInfoRequestListener() {
@Override
public void onCarryOut() {
if (!request.getAccountExists()){
setValidForValue(newValue, false);
setMessage(validator.getContext().getResources().getString(R.string.error_invalid_account));
validator.validationFailed(field);
} else {
setValidForValue(newValue, true);
validator.validationSucceeded(field);
}
}
});
CryptoNetInfoRequests.getInstance().addRequest(request);
}
}

View file

@ -1,110 +1,19 @@
package cy.agorise.crystalwallet.viewmodels.validators; package cy.agorise.crystalwallet.viewmodels.validators;
import android.accounts.Account; import android.content.Context;
import android.content.res.Resources; import android.widget.EditText;
import java.util.ArrayList;
import java.util.List;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListener;
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests;
import cy.agorise.crystalwallet.cryptonetinforequests.ValidateImportBitsharesAccountRequest;
import cy.agorise.crystalwallet.models.AccountSeed;
/** /**
* Created by Henry Varona on 2/10/2017. * Created by Henry Varona on 2/10/2017.
*/ */
public class ImportSeedValidator { public class ImportSeedValidator extends UIValidator {
private ImportSeedValidatorListener listener; public ImportSeedValidator(Context context, EditText pinEdit, EditText pinConfirmationEdit, EditText bitsharesAccountNameEdit, EditText mnemonicEdit){
private List<ValidationField> validationFields; super(context);
private AccountSeed accountSeed; this.addField(new PinValidationField(pinEdit));
private Resources res; this.addField(new PinConfirmationValidationField(pinEdit,pinConfirmationEdit));
this.addField(new BitsharesAccountNameValidationField(bitsharesAccountNameEdit));
private boolean isValid = false; this.addField(new BitsharesAccountMnemonicValidationField(mnemonicEdit,bitsharesAccountNameEdit));
public ImportSeedValidator(Resources res){
this.res = res;
this.validationFields = new ArrayList<ValidationField>();
this.validationFields.add(new ValidationField("pin"));
this.validationFields.add(new ValidationField("pinconfirmation"));
this.validationFields.add(new ValidationField("accountname"));
}
public void setListener(ImportSeedValidatorListener listener){
this.listener = listener;
}
public boolean isValid(){
for(int i=0;i<this.validationFields.size();i++){
ValidationField nextField = this.validationFields.get(i);
if (!nextField.getValid()){
return false;
}
}
return true;
}
public ValidationField getValidationField(String name){
for (int i=0;i<this.validationFields.size();i++){
if (this.validationFields.get(i).getName().equals(name)){
return this.validationFields.get(i);
}
}
return null;
}
public void validatePin(final String pin){
final ValidationField validationField = getValidationField("pin");
validationField.setLastValue(pin);
if ((pin.length() < 6)){
validationField.setValidForValue(pin,false);
validationField.setMessage(res.getString(R.string.pin_number_warning));
listener.onValidationFailed(validationField);
} else {
validationField.setValidForValue(pin, true);
listener.onValidationSucceeded(validationField);
}
}
public void validatePinConfirmation(final String pinConfirmation, final String pin){
final ValidationField validationField = getValidationField("pinconfirmation");
validationField.setLastValue(pinConfirmation);
if (!pinConfirmation.equals(pin)){
validationField.setValidForValue(pinConfirmation,false);
validationField.setMessage(res.getString(R.string.mismatch_pin));
listener.onValidationFailed(validationField);
} else {
validationField.setValidForValue(pinConfirmation, true);
listener.onValidationSucceeded(validationField);
}
}
public void validateAccountName(final String accountName, final String mnemonic){
final ValidationField validationField = getValidationField("accountname");
validationField.setLastValue(accountName);
final ValidateImportBitsharesAccountRequest request = new ValidateImportBitsharesAccountRequest(accountName,mnemonic);
request.setListener(new CryptoNetInfoRequestListener() {
@Override
public void onCarryOut() {
if (!request.getAccountExists()){
validationField.setValidForValue(accountName, false);
validationField.setMessage(res.getString(R.string.account_name_not_exist));
listener.onValidationFailed(validationField);
} else {
validationField.setValidForValue(accountName, true);
listener.onValidationSucceeded(validationField);
}
}
});
CryptoNetInfoRequests.getInstance().addRequest(request);
} }
} }

View file

@ -0,0 +1,42 @@
package cy.agorise.crystalwallet.viewmodels.validators;
import android.content.Context;
import android.widget.EditText;
import cy.agorise.crystalwallet.R;
/**
* Created by Henry Varona on 7/10/2017.
*/
public class PinConfirmationValidationField extends ValidationField {
private EditText pinField;
private EditText pinConfirmationField;
public PinConfirmationValidationField(EditText pinField, EditText pinConfirmationField){
super(pinConfirmationField);
this.pinField = pinField;
this.pinConfirmationField = pinConfirmationField;
}
public void validate(){
String newConfirmationValue = pinConfirmationField.getText().toString();
String newValue = pinField.getText().toString();
String mixedValue = newValue+"_"+newConfirmationValue;
if (mixedValue != this.getLastValue()) {
this.setLastValue(mixedValue);
this.startValidating();
if (!newConfirmationValue.equals(newValue)){
this.setValidForValue(mixedValue,false);
this.setMessage(this.validator.getContext().getResources().getString(R.string.mismatch_pin));
this.validator.validationFailed(this);
} else {
this.setValidForValue(mixedValue, true);
this.validator.validationSucceeded(this);
}
}
}
}

View file

@ -0,0 +1,37 @@
package cy.agorise.crystalwallet.viewmodels.validators;
import android.content.Context;
import android.widget.EditText;
import cy.agorise.crystalwallet.R;
/**
* Created by Henry Varona on 7/10/2017.
*/
public class PinValidationField extends ValidationField {
private EditText pinField;
public PinValidationField(EditText pinField){
super(pinField);
this.pinField = pinField;
}
public void validate(){
String newValue = pinField.getText().toString();
if (newValue != this.getLastValue()) {
this.setLastValue(newValue);
this.startValidating();
if (newValue.length() < 6) {
this.setValidForValue(newValue, false);
this.setMessage(this.validator.getContext().getResources().getString(R.string.pin_number_warning));
this.validator.validationFailed(this);
} else {
this.setValidForValue(newValue, true);
this.validator.validationSucceeded(this);
}
}
}
}

View file

@ -0,0 +1,76 @@
package cy.agorise.crystalwallet.viewmodels.validators;
import android.content.Context;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Henry Varona on 7/10/2017.
*/
abstract class UIValidator {
protected Context context;
protected UIValidatorListener listener;
protected List<ValidationField> validationFields;
public UIValidator(Context context){
this.context = context;
this.validationFields = new ArrayList<ValidationField>();
}
public void addField(ValidationField newField){
this.validationFields.add(newField);
newField.setValidator(this);
}
public Context getContext(){
return this.context;
}
public void setListener(UIValidatorListener listener){
this.listener = listener;
}
public boolean isValid(){
for(int i=0;i<this.validationFields.size();i++){
ValidationField nextField = this.validationFields.get(i);
if (!nextField.getValid()){
return false;
}
}
return true;
}
public void validate(){
for (int i=0;i<this.validationFields.size();i++){
this.validationFields.get(i).validate();
}
}
public int validationFieldsCount(){
return this.validationFields.size();
}
public ValidationField getValidationField(int index){
return this.validationFields.get(index);
}
public void validationFailed(ValidationField field){
this._fireOnValidationFailedEvent(field);
}
public void validationSucceeded(ValidationField field){
this._fireOnValidationSucceededEvent(field);
}
public void _fireOnValidationFailedEvent(ValidationField field){
this.listener.onValidationFailed(field);
}
public void _fireOnValidationSucceededEvent(ValidationField field){
this.listener.onValidationSucceeded(field);
}
}

View file

@ -4,7 +4,7 @@ package cy.agorise.crystalwallet.viewmodels.validators;
* Created by Henry Varona on 2/10/2017. * Created by Henry Varona on 2/10/2017.
*/ */
public interface ImportSeedValidatorListener { public interface UIValidatorListener {
public void onValidationSucceeded(ValidationField field); public void onValidationSucceeded(ValidationField field);
public void onValidationFailed(ValidationField field); public void onValidationFailed(ValidationField field);

View file

@ -1,34 +1,40 @@
package cy.agorise.crystalwallet.viewmodels.validators; package cy.agorise.crystalwallet.viewmodels.validators;
import android.content.Context;
import android.view.View;
/** /**
* Created by Henry Varona on 2/10/2017. * Created by Henry Varona on 2/10/2017.
*/ */
public class ValidationField { public abstract class ValidationField {
public String name; protected String lastValue;
protected String message;
protected boolean validating;
protected Boolean valid;
protected UIValidator validator;
protected View view;
public String lastValue; public ValidationField(View view){
public String message;
public boolean validating;
public boolean valid;
public ValidationField(String name){
this.name = name;
this.lastValue = ""; this.lastValue = "";
this.message = ""; this.message = "";
this.validating = false; this.validating = false;
this.valid = false; this.valid = null;
this.view = view;
} }
public String getName(){ public void setValidator(UIValidator validator){
return this.name; this.validator = validator;
} }
public void startValidating(){ public void startValidating(){
this.valid = null;
this.validating = true; this.validating = true;
} }
abstract public void validate();
public void stopValidating(){ public void stopValidating(){
this.validating = false; this.validating = false;
} }
@ -53,7 +59,7 @@ public class ValidationField {
} }
public boolean getValid(){ public boolean getValid(){
return this.valid; return (this.valid != null?this.valid:false);
} }
public String getLastValue() { public String getLastValue() {
@ -62,9 +68,17 @@ public class ValidationField {
public void setLastValue(String lastValue) { public void setLastValue(String lastValue) {
if (!this.lastValue.equals(lastValue)) { if (!this.lastValue.equals(lastValue)) {
this.valid = false; this.valid = null;
this.validating = false; this.validating = false;
this.lastValue = lastValue; this.lastValue = lastValue;
} }
} }
public void setView(View view){
this.view = view;
}
public View getView(){
return this.view;
}
} }

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

View file

@ -0,0 +1,14 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cy.agorise.crystalwallet.fragments.BalanceFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Balance Fragment"
android:textColor="@android:color/white" />
</FrameLayout>

View file

@ -0,0 +1,13 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cy.agorise.crystalwallet.fragments.ContactsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Contacts Fragment" />
</FrameLayout>

View file

@ -0,0 +1,13 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cy.agorise.crystalwallet.fragments.TransactionsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Transactions Fragment" />
</FrameLayout>

View file

@ -449,4 +449,7 @@
<!-- Import Backup activity --> <!-- Import Backup activity -->
<string name="txt_existing_password">Current backup password</string> <string name="txt_existing_password">Current backup password</string>
<string name="txt_new_pin">New PIN (6+ digits)</string> <string name="txt_new_pin">New PIN (6+ digits)</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources> </resources>