From 5eae79d011cfa586dcca87553251c04a3df71f3c Mon Sep 17 00:00:00 2001 From: Javier Varona Date: Sun, 4 Feb 2018 21:43:20 -0400 Subject: [PATCH] - The user can add contacts (Only the name. Still in progress...) --- app/src/main/AndroidManifest.xml | 52 ++++---- .../activities/BoardActivity.java | 6 + .../activities/CreateContactActivity.java | 113 ++++++++++++++++ .../agorise/crystalwallet/dao/ContactDao.java | 6 + .../fragments/ContactsFragment.java | 29 +++- .../viewmodels/ContactListViewModel.java | 4 + .../viewmodels/ContactViewModel.java | 27 ++++ .../validators/CreateContactValidator.java | 21 +++ .../ContactNameValidationField.java | 59 +++++++++ .../crystalwallet/views/ContactListView.java | 2 - .../res/layout/activity_create_contact.xml | 124 ++++++++++++++++++ 11 files changed, 413 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java create mode 100644 app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java create mode 100644 app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java create mode 100644 app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ContactNameValidationField.java create mode 100644 app/src/main/res/layout/activity_create_contact.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 90f510b..cfdfda8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,12 @@ + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - + + + \ No newline at end of file diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java index 9ef1161..e113438 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java @@ -204,6 +204,12 @@ public class BoardActivity extends AppCompatActivity { } } + @OnClick(R.id.fabAddContact) + public void beginCreateContact(){ + Intent intent = new Intent(this, CreateContactActivity.class); + startActivity(intent); + } + /* * dispatch the user to the receive fragment using this account */ diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java new file mode 100644 index 0000000..ae5aa5f --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java @@ -0,0 +1,113 @@ +package cy.agorise.crystalwallet.activities; + +import android.arch.lifecycle.ViewModelProviders; +import android.content.Intent; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.Editable; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.OnTextChanged; +import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListener; +import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests; +import cy.agorise.crystalwallet.cryptonetinforequests.ValidateCreateBitsharesAccountRequest; +import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.GrapheneAccount; +import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; +import cy.agorise.crystalwallet.viewmodels.ContactViewModel; +import cy.agorise.crystalwallet.viewmodels.validators.CreateContactValidator; +import cy.agorise.crystalwallet.viewmodels.validators.CreateSeedValidator; +import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener; +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField; + +public class CreateContactActivity extends AppCompatActivity implements UIValidatorListener { + + @BindView(R.id.etName) + EditText etName; + @BindView(R.id.tvNameError) + TextView tvNameError; + @BindView(R.id.btnCancel) + Button btnCancel; + @BindView(R.id.btnCreate) + Button btnCreate; + + CreateContactValidator createContactValidator; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_create_contact); + ButterKnife.bind(this); + + btnCreate.setEnabled(false); + createContactValidator = new CreateContactValidator(this.getApplicationContext(),etName); + createContactValidator.setListener(this); + } + + @OnTextChanged(value = R.id.etName, + callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) + void afterContactNameChanged(Editable editable) { + this.createContactValidator.validate(); + } + + + @OnClick(R.id.btnCancel) + public void cancel(){ + this.finish(); + } + + @OnClick(R.id.btnCreate) + public void createContact(){ + if (this.createContactValidator.isValid()) { + Contact newContact = new Contact(); + newContact.setName(etName.getText().toString()); + ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); + if (contactViewModel.addContact(newContact)){ + this.finish(); + } else { + createContactValidator.validate(); + } + } + } + + @Override + public void onValidationSucceeded(final ValidationField field) { + final CreateContactActivity activity = this; + + activity.runOnUiThread(new Runnable() { + public void run() { + + if (field.getView() == etName) { + tvNameError.setText(""); + } + + if (activity.createContactValidator.isValid()){ + btnCreate.setEnabled(true); + } else { + btnCreate.setEnabled(false); + } + } + }); + } + + @Override + public void onValidationFailed(final ValidationField field) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (field.getView() == etName) { + tvNameError.setText(field.getMessage()); + } + } + }); + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java b/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java index 77dd3fd..13425ea 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java +++ b/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java @@ -26,4 +26,10 @@ public interface ContactDao { @Query("SELECT * FROM contact WHERE id = :id") LiveData getById(long id); + + @Query("SELECT count(*) FROM contact WHERE name = :name") + boolean existsByName(String name); + + @Insert(onConflict = OnConflictStrategy.ABORT) + public long[] add(Contact... contacts); } diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java index 558d81b..34b2652 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ContactsFragment.java @@ -1,14 +1,28 @@ package cy.agorise.crystalwallet.fragments; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.Observer; +import android.arch.lifecycle.ViewModelProviders; +import android.arch.paging.PagedList; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import butterknife.BindView; +import butterknife.ButterKnife; import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; +import cy.agorise.crystalwallet.views.ContactListView; public class ContactsFragment extends Fragment { + + @BindView(R.id.vContactListView) + ContactListView contactListView; + public ContactsFragment() { // Required empty public constructor } @@ -29,6 +43,19 @@ public class ContactsFragment extends Fragment { 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 v = inflater.inflate(R.layout.fragment_contacts, container, false); + ButterKnife.bind(this, v); + + ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class); + LiveData> contactsLiveData = contactListViewModel.getContactList(); + + contactsLiveData.observe(this, new Observer>() { + @Override + public void onChanged(@Nullable PagedList contacts) { + contactListView.setData(contacts); + } + }); + + return v; } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java index ec076d9..4bd2522 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactListViewModel.java @@ -33,4 +33,8 @@ public class ContactListViewModel extends AndroidViewModel { public LiveData> getContactList(){ return this.contactList; } + + public boolean contactExists(String name){ + return this.db.contactDao().existsByName(name); + } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java new file mode 100644 index 0000000..1ac999e --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java @@ -0,0 +1,27 @@ +package cy.agorise.crystalwallet.viewmodels; + +import android.app.Application; +import android.arch.lifecycle.AndroidViewModel; +import android.arch.lifecycle.LiveData; +import android.arch.paging.PagedList; + +import cy.agorise.crystalwallet.dao.CrystalDatabase; +import cy.agorise.crystalwallet.models.Contact; + +/** + * Created by Henry Varona on 2/4/2018. + */ + +public class ContactViewModel extends AndroidViewModel { + + private CrystalDatabase db; + + public ContactViewModel(Application application) { + super(application); + this.db = CrystalDatabase.getAppDatabase(application.getApplicationContext()); + } + + public boolean addContact(Contact contact){ + return this.db.contactDao().add(contact)[0] >= 0; + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java new file mode 100644 index 0000000..34e43ae --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/CreateContactValidator.java @@ -0,0 +1,21 @@ +package cy.agorise.crystalwallet.viewmodels.validators; + +import android.content.Context; +import android.widget.EditText; + +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.BitsharesAccountNameDoesntExistsValidationField; +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ContactNameValidationField; +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.PinConfirmationValidationField; +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.PinValidationField; + +/** + * Created by Henry Varona on 2/2/2018. + */ + +public class CreateContactValidator extends UIValidator { + + public CreateContactValidator(Context context, EditText nameEdit){ + super(context); + this.addField(new ContactNameValidationField(nameEdit)); + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ContactNameValidationField.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ContactNameValidationField.java new file mode 100644 index 0000000..cdca074 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ContactNameValidationField.java @@ -0,0 +1,59 @@ +package cy.agorise.crystalwallet.viewmodels.validators.validationfields; + +import android.arch.lifecycle.LifecycleOwner; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.Observer; +import android.arch.lifecycle.ViewModelProviders; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; +import android.widget.EditText; +import android.widget.Spinner; + +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.ValidateExistBitsharesAccountRequest; +import cy.agorise.crystalwallet.models.GeneralSetting; +import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; +import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel; + +/** + * Created by Henry Varona on 2/03/2017. + */ + +public class ContactNameValidationField extends ValidationField { + + private EditText nameField; + + public ContactNameValidationField(EditText nameField){ + super(nameField); + this.nameField = nameField; + } + + public void validate(){ + final String newValue = this.nameField.getText().toString(); + + + if (!newValue.equals("")) { + if (!newValue.equals(this.getLastValue())) { + this.setLastValue(newValue); + this.startValidating(); + + ContactListViewModel contactListViewModel = ViewModelProviders.of((FragmentActivity) view.getContext()).get(ContactListViewModel.class); + if (contactListViewModel.contactExists(newValue)) { + this.setMessageForValue(newValue, "This name is already used by another contact."); + this.setValidForValue(newValue, false); + } else { + this.setValidForValue(newValue, true); + } + } + } else { + this.setLastValue(""); + this.startValidating(); + this.setMessageForValue("", ""); + this.setValidForValue("", false); + } + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java index e9efce9..854be6b 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java +++ b/app/src/main/java/cy/agorise/crystalwallet/views/ContactListView.java @@ -12,9 +12,7 @@ import android.widget.RelativeLayout; import cy.agorise.crystalwallet.R; import cy.agorise.crystalwallet.models.Contact; -import cy.agorise.crystalwallet.models.CryptoCoinTransaction; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; -import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel; /** * Created by Henry Varona on 1/15/2018. diff --git a/app/src/main/res/layout/activity_create_contact.xml b/app/src/main/res/layout/activity_create_contact.xml new file mode 100644 index 0000000..7576a93 --- /dev/null +++ b/app/src/main/res/layout/activity_create_contact.xml @@ -0,0 +1,124 @@ + + + + + + + + + + +