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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+