diff --git a/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json index 75985a4..01dada3 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": "1b825c6a18815f35456f569f59868945", + "identityHash": "6f4a0d464f042d577c584ed532bffd2c", "entities": [ { "tableName": "account_seed", @@ -284,8 +284,14 @@ }, { "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`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `contact_id` INTEGER NOT NULL, `crypto_net` TEXT NOT NULL, `address` TEXT)", "fields": [ + { + "fieldPath": "mId", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, { "fieldPath": "mContactId", "columnName": "contact_id", @@ -307,12 +313,19 @@ ], "primaryKey": { "columnNames": [ - "contact_id", - "crypto_net" + "id" ], - "autoGenerate": false + "autoGenerate": true }, "indices": [ + { + "name": "index_contact_address_id", + "unique": true, + "columnNames": [ + "id" + ], + "createSql": "CREATE UNIQUE INDEX `index_contact_address_id` ON `${TABLE_NAME}` (`id`)" + }, { "name": "index_contact_address_contact_id_crypto_net", "unique": true, @@ -665,7 +678,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, \"1b825c6a18815f35456f569f59868945\")" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"6f4a0d464f042d577c584ed532bffd2c\")" ] } } \ 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 6aa7596..41c6d00 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateContactActivity.java @@ -1,13 +1,18 @@ package cy.agorise.crystalwallet.activities; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; 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.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; @@ -31,9 +36,11 @@ 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.ModifyContactValidator; import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener; import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField; import cy.agorise.crystalwallet.views.ContactAddressListAdapter; +import cy.agorise.crystalwallet.views.ContactViewHolder; public class CreateContactActivity extends AppCompatActivity implements UIValidatorListener { @@ -45,6 +52,8 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida Button btnCancel; @BindView(R.id.btnCreate) Button btnCreate; + @BindView(R.id.btnModify) + Button btnModify; @BindView(R.id.rvContactAddresses) RecyclerView rvContactAddresses; @BindView(R.id.btnAddAddress) @@ -53,6 +62,9 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida ContactAddressListAdapter listAdapter; CreateContactValidator createContactValidator; + ModifyContactValidator modifyContactValidator; + + Contact contact; @Override protected void onCreate(Bundle savedInstanceState) { @@ -62,21 +74,81 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida 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); + long contactId = this.getIntent().getLongExtra("CONTACT_ID",-1); + + btnCreate.setVisibility(View.GONE); + btnModify.setVisibility(View.GONE); + + if (contactId >= 0){ + final ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); + + contactViewModel.init(contactId); + LiveData contactLiveData = contactViewModel.getContact(); + final CreateContactActivity thisActivity = this; + + contactLiveData.observe(this, new Observer() { + @Override + public void onChanged(@Nullable Contact contactChanged) { + if (contactChanged != null){ + contact = contactChanged; + etName.setText(contact.getName()); + + LiveData> contactAddresses = contactViewModel.getContactAddresses(); + + contactAddresses.observe(thisActivity, new Observer>() { + @Override + public void onChanged(@Nullable List contactAddresses) { + contactAddressList = contactAddresses; + listAdapter.setList(contactAddressList); + listAdapter.notifyDataSetChanged(); + } + }); + + modifyContactValidator = new ModifyContactValidator(thisActivity.getApplicationContext(),contact,etName); + modifyContactValidator.setListener(thisActivity); + btnModify.setVisibility(View.VISIBLE); + } else { + //No contact was found, this will exit the activity + finish(); + } + } + }); + } else { + contactAddressList = new ArrayList(); + listAdapter.setList(contactAddressList); + createContactValidator = new CreateContactValidator(this.getApplicationContext(),etName); + createContactValidator.setListener(this); + + btnCreate.setVisibility(View.VISIBLE); + } + } + + public void validate(){ + if (this.createContactValidator != null){ + this.createContactValidator.validate(); + } else if (this.modifyContactValidator != null){ + this.modifyContactValidator.validate(); + } + } + + public boolean isValid(){ + if (this.createContactValidator != null){ + return this.createContactValidator.isValid(); + } else if (this.modifyContactValidator != null){ + return this.modifyContactValidator.isValid(); + } + + return false; } @OnTextChanged(value = R.id.etName, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void afterContactNameChanged(Editable editable) { - this.createContactValidator.validate(); + this.validate(); } @OnClick(R.id.btnAddAddress) @@ -91,6 +163,25 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida this.finish(); } + @OnClick(R.id.btnModify) + public void modifyContact(){ + if (this.modifyContactValidator.isValid()) { + this.contact.setName(etName.getText().toString()); + this.contact.clearAddresses(); + + for (ContactAddress contactAddress : contactAddressList){ + this.contact.addAddress(contactAddress); + } + + ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class); + if (contactViewModel.modifyContact(this.contact)){ + this.finish(); + } else { + this.modifyContactValidator.validate(); + } + } + } + @OnClick(R.id.btnCreate) public void createContact(){ if (this.createContactValidator.isValid()) { @@ -121,7 +212,7 @@ public class CreateContactActivity extends AppCompatActivity implements UIValida tvNameError.setText(""); } - if (activity.createContactValidator.isValid()){ + if (activity.isValid()){ btnCreate.setEnabled(true); } else { btnCreate.setEnabled(false); 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 5c0fad9..8447c2b 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java +++ b/app/src/main/java/cy/agorise/crystalwallet/dao/ContactDao.java @@ -6,6 +6,7 @@ import android.arch.persistence.room.Dao; import android.arch.persistence.room.Insert; import android.arch.persistence.room.OnConflictStrategy; import android.arch.persistence.room.Query; +import android.arch.persistence.room.Update; import java.util.List; @@ -31,9 +32,21 @@ public interface ContactDao { @Query("SELECT count(*) FROM contact WHERE name = :name") boolean existsByName(String name); + @Query("SELECT * FROM contact_address WHERE contact_id = :contactId") + LiveData> getContactAddresses(long contactId); + + @Update(onConflict = OnConflictStrategy.ABORT) + public void update(Contact... contacts); + @Insert(onConflict = OnConflictStrategy.ABORT) public long[] add(Contact... contacts); @Insert(onConflict = OnConflictStrategy.ABORT) public void addAddresses(ContactAddress... contactAddresses); + + @Update(onConflict = OnConflictStrategy.REPLACE) + public void updateAddresses(ContactAddress... contactAddresses); + + @Update(onConflict = OnConflictStrategy.REPLACE) + public void updateAddressesFields(ContactAddress... contactAddresses); } 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 730f0c3..b65f3f9 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java +++ b/app/src/main/java/cy/agorise/crystalwallet/models/Contact.java @@ -71,6 +71,12 @@ public class Contact { return this.mAddresses.get(index); } + public void clearAddresses(){ + if (this.mAddresses != null) { + this.mAddresses.clear(); + } + } + public void addAddress(ContactAddress address){ if (this.mAddresses == null) { this.mAddresses = new ArrayList(); 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 8b43602..85d9930 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java +++ b/app/src/main/java/cy/agorise/crystalwallet/models/ContactAddress.java @@ -4,6 +4,7 @@ package cy.agorise.crystalwallet.models; import android.arch.persistence.room.ColumnInfo; import android.arch.persistence.room.Entity; import android.arch.persistence.room.Index; +import android.arch.persistence.room.PrimaryKey; import android.support.annotation.NonNull; import android.support.v7.recyclerview.extensions.DiffCallback; @@ -16,10 +17,16 @@ import cy.agorise.crystalwallet.enums.CryptoNet; */ @Entity(tableName="contact_address", - primaryKeys = {"contact_id","crypto_net"}, - indices = {@Index(value = {"contact_id","crypto_net"}, unique=true)}) + indices = {@Index(value = {"id"}, unique=true),@Index(value = {"contact_id","crypto_net"}, unique=true)}) public class ContactAddress { + /** + * The id on the database + */ + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = "id") + private long mId; + @ColumnInfo(name = "contact_id") private long mContactId; @@ -33,6 +40,14 @@ public class ContactAddress { @ColumnInfo(name="address") private String mAddress; + public long getId() { + return mId; + } + + public void setId(long id) { + this.mId = id; + } + public long getContactId() { return mContactId; } 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 b286ee5..1951215 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/ContactViewModel.java @@ -5,6 +5,8 @@ import android.arch.lifecycle.AndroidViewModel; import android.arch.lifecycle.LiveData; import android.arch.paging.PagedList; +import java.util.List; + import cy.agorise.crystalwallet.dao.CrystalDatabase; import cy.agorise.crystalwallet.models.Contact; import cy.agorise.crystalwallet.models.ContactAddress; @@ -16,12 +18,43 @@ import cy.agorise.crystalwallet.models.ContactAddress; public class ContactViewModel extends AndroidViewModel { private CrystalDatabase db; + private LiveData contact; + private LiveData> contactAddresses; public ContactViewModel(Application application) { super(application); this.db = CrystalDatabase.getAppDatabase(application.getApplicationContext()); } + public void init(long contactId){ + this.contact = this.db.contactDao().getById(contactId); + this.contactAddresses = this.db.contactDao().getContactAddresses(contactId); + } + + public LiveData getContact(){ + return this.contact; + } + + public LiveData> getContactAddresses(){ + return this.contactAddresses; + } + + public boolean modifyContact(Contact contact){ + this.db.contactDao().update(contact); + + for (int i=0;i 0){ + this.db.contactDao().updateAddresses(nextAddress); + } else { + nextAddress.setContactId(contact.getId()); + this.db.contactDao().addAddresses(nextAddress); + } + } + + return true; + } + public boolean addContact(Contact contact){ long newContactId = this.db.contactDao().add(contact)[0]; boolean contactWasAdded = newContactId >= 0; diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java new file mode 100644 index 0000000..0140e8e --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/ModifyContactValidator.java @@ -0,0 +1,19 @@ +package cy.agorise.crystalwallet.viewmodels.validators; + +import android.content.Context; +import android.widget.EditText; + +import cy.agorise.crystalwallet.models.Contact; +import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ContactNameValidationField; + +/** + * Created by Henry Varona on 2/11/2018. + */ + +public class ModifyContactValidator extends UIValidator { + + public ModifyContactValidator(Context context, Contact contact, EditText nameEdit){ + super(context); + this.addField(new ContactNameValidationField(nameEdit, contact)); + } +} 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 index cdca074..275c550 100644 --- 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 @@ -15,6 +15,7 @@ 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.Contact; import cy.agorise.crystalwallet.models.GeneralSetting; import cy.agorise.crystalwallet.viewmodels.ContactListViewModel; import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel; @@ -26,15 +27,31 @@ import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel; public class ContactNameValidationField extends ValidationField { private EditText nameField; + private Contact contact; public ContactNameValidationField(EditText nameField){ super(nameField); this.nameField = nameField; + this.contact = null; + } + + public ContactNameValidationField(EditText nameField, Contact contact){ + super(nameField); + this.nameField = nameField; + this.contact = contact; } public void validate(){ final String newValue = this.nameField.getText().toString(); + if (this.contact != null){ + if (this.contact.getName().equals(newValue)){ + this.setLastValue(newValue); + this.startValidating(); + this.setValidForValue(newValue, true); + return; + } + } if (!newValue.equals("")) { if (!newValue.equals(this.getLastValue())) { diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java index 832a97d..711c9ab 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java +++ b/app/src/main/java/cy/agorise/crystalwallet/views/ContactAddressViewHolder.java @@ -30,6 +30,8 @@ public class ContactAddressViewHolder extends RecyclerView.ViewHolder { private Spinner spCryptoNet; private EditText etAddress; private Context context; + private CryptoNet[] cryptoNetArray; + private ArrayAdapter cryptoNetSpinnerAdapter; public ContactAddressViewHolder(View itemView) { super(itemView); @@ -40,8 +42,8 @@ public class ContactAddressViewHolder extends RecyclerView.ViewHolder { //load spinners values - CryptoNet[] cryptoNetArray = CryptoNet.values(); - ArrayAdapter cryptoNetSpinnerAdapter = new ArrayAdapter( + cryptoNetArray = CryptoNet.values(); + cryptoNetSpinnerAdapter = new ArrayAdapter( this.context, android.R.layout.simple_list_item_1, cryptoNetArray @@ -64,6 +66,18 @@ public class ContactAddressViewHolder extends RecyclerView.ViewHolder { if (contactAddress == null){ this.clear(); } else { + etAddress.setText(contactAddress.getAddress()); + + CryptoNet nextCryptoNet; + for (int i=0;i adapterView, View view, int i, long l) { diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java b/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java index 429acf0..80c556d 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java +++ b/app/src/main/java/cy/agorise/crystalwallet/views/ContactViewHolder.java @@ -1,12 +1,15 @@ package cy.agorise.crystalwallet.views; import android.content.Context; +import android.content.Intent; +import android.provider.ContactsContract; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.activities.CreateContactActivity; import cy.agorise.crystalwallet.models.Contact; /** @@ -19,6 +22,7 @@ public class ContactViewHolder extends RecyclerView.ViewHolder { private TextView tvName; private ImageView ivThumbnail; private TextView tvLastPaid; + private ImageView ivDeleteContact; private Context context; public ContactViewHolder(View itemView) { @@ -27,6 +31,7 @@ public class ContactViewHolder extends RecyclerView.ViewHolder { tvName = (TextView) itemView.findViewById(R.id.tvContactName); ivThumbnail = (ImageView) itemView.findViewById(R.id.ivContactThumbnail); tvLastPaid = (TextView) itemView.findViewById(R.id.tvLastPaid); + ivDeleteContact = (ImageView) itemView.findViewById(R.id.ivDeleteContact); this.context = itemView.getContext(); } @@ -49,6 +54,22 @@ public class ContactViewHolder extends RecyclerView.ViewHolder { } else { tvName.setText(contact.getName()); tvLastPaid.setText("Paid: 1 Jan, 2001 01:01"); + + this.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(itemView.getContext(), CreateContactActivity.class); + intent.putExtra("CONTACT_ID", contact.getId()); + itemView.getContext().startActivity(intent); + } + }); + + this.ivDeleteContact.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // + } + }); } } } diff --git a/app/src/main/res/layout/activity_create_contact.xml b/app/src/main/res/layout/activity_create_contact.xml index 8af9025..f64d603 100644 --- a/app/src/main/res/layout/activity_create_contact.xml +++ b/app/src/main/res/layout/activity_create_contact.xml @@ -81,6 +81,16 @@ android:padding="10dp" android:text="Create Contact" android:textColor="@color/white" /> +