- Contacts can be created

- Contacts can have multiple addresses for every crypto net (still in progress...)
master
Javier Varona 2018-02-07 21:47:58 -04:00
parent 5eae79d011
commit 58afdb144b
11 changed files with 298 additions and 13 deletions

View File

@ -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\")"
]
}
}

View File

@ -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<ContactAddress> 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<ContactAddress>();
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();

View File

@ -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);
}

View File

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

View File

@ -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<ContactAddress>();
}
this.mAddresses.add(address);
address.setContactId(this.getId());
}
public static final DiffCallback<Contact> DIFF_CALLBACK = new DiffCallback<Contact>() {

View File

@ -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);
}
}

View File

@ -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<contact.addressesCount();i++){
ContactAddress nextAddress = contact.getAddress(i);
nextAddress.setContactId(newContactId);
this.db.contactDao().addAddresses(nextAddress);
}
return contactWasAdded;
}
}

View File

@ -0,0 +1,41 @@
package cy.agorise.crystalwallet.views;
import android.support.v7.recyclerview.extensions.ListAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.models.ContactAddress;
/**
* Created by Henry Varona on 2/5/2018.
*
* An adapter to show the elements of a list of contacts addresses
*/
public class ContactAddressListAdapter extends ListAdapter<ContactAddress, ContactAddressViewHolder> {
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();
}
}
}

View File

@ -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<CryptoNet> cryptoNetSpinnerAdapter = new ArrayAdapter<CryptoNet>(
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());
}
}
}

View File

@ -37,6 +37,21 @@
android:maxLines="1"
android:textColor="@color/red" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvContactAddresses"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
<Button
android:id="@+id/btnAddAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rvContactAddresses"
android:text="Add"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<Spinner
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:id="@+id/spCryptoNet"/>
<EditText
android:id="@+id/etAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/spCryptoNet"
android:layout_alignParentEnd="true"
android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>