From 58afdb144b200773b0cdc6d6819a4328fedcefb3 Mon Sep 17 00:00:00 2001 From: Javier Varona Date: Wed, 7 Feb 2018 21:47:58 -0400 Subject: [PATCH] - Contacts can be created - Contacts can have multiple addresses for every crypto net (still in progress...) --- .../2.json | 47 ++++++++- .../activities/CreateContactActivity.java | 32 ++++++ .../agorise/crystalwallet/dao/ContactDao.java | 4 + .../crystalwallet/dao/CrystalDatabase.java | 2 + .../agorise/crystalwallet/models/Contact.java | 5 + .../crystalwallet/models/ContactAddress.java | 26 +++-- .../viewmodels/ContactViewModel.java | 12 ++- .../views/ContactAddressListAdapter.java | 41 ++++++++ .../views/ContactAddressViewHolder.java | 97 +++++++++++++++++++ .../res/layout/activity_create_contact.xml | 15 +++ .../res/layout/contact_address_list_item.xml | 30 ++++++ 11 files changed, 298 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressListAdapter.java create mode 100644 app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java create mode 100644 app/src/main/res/layout/contact_address_list_item.xml diff --git a/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json index 2f9409f..75985a4 100644 --- a/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json +++ b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 2, - "identityHash": "a44ccb96c8213951403ed2a283fb3367", + "identityHash": "1b825c6a18815f35456f569f59868945", "entities": [ { "tableName": "account_seed", @@ -282,6 +282,49 @@ ], "foreignKeys": [] }, + { + "tableName": "contact_address", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`contact_id` INTEGER NOT NULL, `crypto_net` TEXT NOT NULL, `address` TEXT, PRIMARY KEY(`contact_id`, `crypto_net`))", + "fields": [ + { + "fieldPath": "mContactId", + "columnName": "contact_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mCryptoNet", + "columnName": "crypto_net", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mAddress", + "columnName": "address", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "contact_id", + "crypto_net" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_contact_address_contact_id_crypto_net", + "unique": true, + "columnNames": [ + "contact_id", + "crypto_net" + ], + "createSql": "CREATE UNIQUE INDEX `index_contact_address_contact_id_crypto_net` ON `${TABLE_NAME}` (`contact_id`, `crypto_net`)" + } + ], + "foreignKeys": [] + }, { "tableName": "crypto_currency", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `crypto_net` TEXT, `precision` INTEGER NOT NULL)", @@ -622,7 +665,7 @@ ], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"a44ccb96c8213951403ed2a283fb3367\")" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"1b825c6a18815f35456f569f59868945\")" ] } } \ No newline at end of file diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java index ae5aa5f..6aa7596 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java @@ -5,12 +5,17 @@ import android.content.Intent; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import java.util.ArrayList; +import java.util.List; + import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; @@ -20,6 +25,7 @@ import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListen import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests; import cy.agorise.crystalwallet.cryptonetinforequests.ValidateCreateBitsharesAccountRequest; import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.ContactAddress; import cy.agorise.crystalwallet.models.GrapheneAccount; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; import cy.agorise.crystalwallet.viewmodels.ContactViewModel; @@ -27,6 +33,7 @@ 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; +import cy.agorise.crystalwallet.views.ContactAddressListAdapter; public class CreateContactActivity extends AppCompatActivity implements UIValidatorListener { @@ -38,6 +45,12 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida Button btnCancel; @BindView(R.id.btnCreate) Button btnCreate; + @BindView(R.id.rvContactAddresses) + RecyclerView rvContactAddresses; + @BindView(R.id.btnAddAddress) + Button btnAddAddress; + List contactAddressList; + ContactAddressListAdapter listAdapter; CreateContactValidator createContactValidator; @@ -48,6 +61,14 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida ButterKnife.bind(this); btnCreate.setEnabled(false); + + //Initializes the recyclerview + contactAddressList = new ArrayList(); + listAdapter = new ContactAddressListAdapter(); + listAdapter.setList(contactAddressList); + rvContactAddresses.setLayoutManager(new LinearLayoutManager(getApplicationContext())); + rvContactAddresses.setAdapter(listAdapter); + createContactValidator = new CreateContactValidator(this.getApplicationContext(),etName); createContactValidator.setListener(this); } @@ -58,6 +79,12 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida this.createContactValidator.validate(); } + @OnClick(R.id.btnAddAddress) + public void addAddress(){ + ContactAddress newContactAddress = new ContactAddress(); + this.contactAddressList.add(newContactAddress); + this.listAdapter.notifyDataSetChanged(); + } @OnClick(R.id.btnCancel) public void cancel(){ @@ -69,6 +96,11 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida if (this.createContactValidator.isValid()) { Contact newContact = new Contact(); newContact.setName(etName.getText().toString()); + + for (ContactAddress contactAddress : contactAddressList){ + newContact.addAddress(contactAddress); + } + ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); if (contactViewModel.addContact(newContact)){ this.finish(); 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 13425ea..5c0fad9 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java +++ b/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java @@ -10,6 +10,7 @@ import android.arch.persistence.room.Query; import java.util.List; import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.ContactAddress; import cy.agorise.crystalwallet.models.CryptoCoinTransaction; /** @@ -32,4 +33,7 @@ public interface ContactDao { @Insert(onConflict = OnConflictStrategy.ABORT) public long[] add(Contact... contacts); + + @Insert(onConflict = OnConflictStrategy.ABORT) + public void addAddresses(ContactAddress... contactAddresses); } diff --git a/app/src/main/java/cy/agorise/crystalwallet/dao/CrystalDatabase.java b/app/src/main/java/cy/agorise/crystalwallet/dao/CrystalDatabase.java index dc8b951..d0c79ba 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/dao/CrystalDatabase.java +++ b/app/src/main/java/cy/agorise/crystalwallet/dao/CrystalDatabase.java @@ -10,6 +10,7 @@ import cy.agorise.crystalwallet.dao.converters.Converters; import cy.agorise.crystalwallet.models.AccountSeed; import cy.agorise.crystalwallet.models.BitsharesAssetInfo; import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.ContactAddress; import cy.agorise.crystalwallet.models.CryptoCoinBalance; import cy.agorise.crystalwallet.models.CryptoCoinTransaction; import cy.agorise.crystalwallet.models.CryptoCurrency; @@ -28,6 +29,7 @@ import cy.agorise.crystalwallet.models.GrapheneAccountInfo; CryptoNetAccount.class, CryptoCoinTransaction.class, Contact.class, + ContactAddress.class, CryptoCurrency.class, CryptoCoinBalance.class, GrapheneAccountInfo.class, diff --git a/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java b/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java index 1cc3d6e..730f0c3 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java +++ b/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java @@ -10,6 +10,7 @@ import android.arch.persistence.room.PrimaryKey; import android.support.annotation.NonNull; import android.support.v7.recyclerview.extensions.DiffCallback; +import java.util.ArrayList; import java.util.List; /** @@ -71,7 +72,11 @@ public class Contact { } public void addAddress(ContactAddress address){ + if (this.mAddresses == null) { + this.mAddresses = new ArrayList(); + } this.mAddresses.add(address); + address.setContactId(this.getId()); } public static final DiffCallback DIFF_CALLBACK = new DiffCallback() { diff --git a/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java b/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java index ae247dd..8b43602 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java +++ b/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java @@ -7,6 +7,8 @@ import android.arch.persistence.room.Index; import android.support.annotation.NonNull; import android.support.v7.recyclerview.extensions.DiffCallback; +import cy.agorise.crystalwallet.enums.CryptoNet; + /** * Represents a user contact address * @@ -14,15 +16,19 @@ import android.support.v7.recyclerview.extensions.DiffCallback; */ @Entity(tableName="contact_address", - primaryKeys = {"contact_id","crypto_currency_id"}, - indices = {@Index(value = {"contact_id","crypto_currency_id"}, unique=true)}) + primaryKeys = {"contact_id","crypto_net"}, + indices = {@Index(value = {"contact_id","crypto_net"}, unique=true)}) public class ContactAddress { @ColumnInfo(name = "contact_id") private long mContactId; - @ColumnInfo(name = "crypto_currency_id") - private long mCryptoCurrencyId; + /** + * The crypto net of the address + */ + @NonNull + @ColumnInfo(name = "crypto_net") + private CryptoNet mCryptoNet; @ColumnInfo(name="address") private String mAddress; @@ -35,12 +41,12 @@ public class ContactAddress { this.mContactId = contactId; } - public long getCryptoCurrencyId() { - return mCryptoCurrencyId; + public CryptoNet getCryptoNet() { + return mCryptoNet; } - public void setCryptoCurrencyId(long cryptoCurrencyId) { - this.mCryptoCurrencyId = cryptoCurrencyId; + public void setCryptoNet(CryptoNet cryptoNet) { + this.mCryptoNet = cryptoNet; } public String getAddress() { @@ -56,7 +62,7 @@ public class ContactAddress { public boolean areItemsTheSame( @NonNull ContactAddress oldContactAddress, @NonNull ContactAddress newContactAddress) { return (oldContactAddress.getContactId() == newContactAddress.getContactId()) - && (oldContactAddress.getCryptoCurrencyId() == newContactAddress.getCryptoCurrencyId()); + && (oldContactAddress.getCryptoNet() == newContactAddress.getCryptoNet()); } @Override public boolean areContentsTheSame( @@ -73,7 +79,7 @@ public class ContactAddress { ContactAddress that = (ContactAddress) o; if (mContactId != that.mContactId) return false; - if (mCryptoCurrencyId != that.mCryptoCurrencyId) return false; + if (mCryptoNet != that.mCryptoNet) return false; return mAddress.equals(that.mAddress); } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java index 1ac999e..b286ee5 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java @@ -7,6 +7,7 @@ import android.arch.paging.PagedList; import cy.agorise.crystalwallet.dao.CrystalDatabase; import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.ContactAddress; /** * Created by Henry Varona on 2/4/2018. @@ -22,6 +23,15 @@ public class ContactViewModel extends AndroidViewModel { } public boolean addContact(Contact contact){ - return this.db.contactDao().add(contact)[0] >= 0; + long newContactId = this.db.contactDao().add(contact)[0]; + boolean contactWasAdded = newContactId >= 0; + + for (int i=0;i { + + public ContactAddressListAdapter() { + super(ContactAddress.DIFF_CALLBACK); + } + + @Override + public ContactAddressViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.contact_address_list_item,parent,false); + + return new ContactAddressViewHolder(v); + } + + @Override + public void onBindViewHolder(ContactAddressViewHolder holder, int position) { + ContactAddress contactAddress = getItem(position); + if (contactAddress != null) { + holder.bindTo(contactAddress); + } else { + holder.clear(); + } + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java new file mode 100644 index 0000000..832a97d --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java @@ -0,0 +1,97 @@ +package cy.agorise.crystalwallet.views; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Spinner; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.enums.CryptoNet; +import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.models.ContactAddress; + +/** + * Created by Henry Varona on 2/5/2017. + * + * Represents an element view from the Contact Address List + */ + +public class ContactAddressViewHolder extends RecyclerView.ViewHolder { + private Spinner spCryptoNet; + private EditText etAddress; + private Context context; + + public ContactAddressViewHolder(View itemView) { + super(itemView); + //TODO: use ButterKnife to load this + spCryptoNet = (Spinner) itemView.findViewById(R.id.spCryptoNet); + etAddress = (EditText) itemView.findViewById(R.id.etAddress); + this.context = itemView.getContext(); + + + //load spinners values + CryptoNet[] cryptoNetArray = CryptoNet.values(); + ArrayAdapter cryptoNetSpinnerAdapter = new ArrayAdapter( + this.context, + android.R.layout.simple_list_item_1, + cryptoNetArray + ); + spCryptoNet.setAdapter(cryptoNetSpinnerAdapter); + } + + /* + * Clears the information in this element view + */ + public void clear(){ + spCryptoNet.setSelection(0); + etAddress.setText(""); + } + + /* + * Binds this view with the data of an element of the list + */ + public void bindTo(final ContactAddress contactAddress) { + if (contactAddress == null){ + this.clear(); + } else { + spCryptoNet.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + contactAddress.setCryptoNet(((CryptoNet)spCryptoNet.getSelectedItem())); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + // + } + }); + etAddress.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + // + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + // + } + + @Override + public void afterTextChanged(Editable editable) { + contactAddress.setAddress(editable.toString()); + } + }); + //etAddress.setText(contactAddress.getAddress()); + } + } +} diff --git a/app/src/main/res/layout/activity_create_contact.xml b/app/src/main/res/layout/activity_create_contact.xml index 7576a93..8af9025 100644 --- a/app/src/main/res/layout/activity_create_contact.xml +++ b/app/src/main/res/layout/activity_create_contact.xml @@ -37,6 +37,21 @@ android:maxLines="1" android:textColor="@color/red" /> + + +