- Now the user can select a contact in the Send Fragment
This commit is contained in:
parent
033a959e00
commit
09ae532446
9 changed files with 400 additions and 0 deletions
|
@ -3,6 +3,7 @@ package cy.agorise.crystalwallet.dao;
|
|||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.paging.LivePagedListProvider;
|
||||
import android.arch.persistence.room.Dao;
|
||||
import android.arch.persistence.room.Delete;
|
||||
import android.arch.persistence.room.Insert;
|
||||
import android.arch.persistence.room.OnConflictStrategy;
|
||||
import android.arch.persistence.room.Query;
|
||||
|
@ -26,6 +27,9 @@ public interface ContactDao {
|
|||
@Query("SELECT * FROM contact ORDER BY name ASC")
|
||||
LivePagedListProvider<Integer, Contact> contactsByName();
|
||||
|
||||
@Query("SELECT c.* FROM contact c WHERE c.id IN (SELECT DISTINCT(ca.contact_id) FROM contact_address ca WHERE ca.crypto_net == :cryptoNet) ORDER BY name ASC")
|
||||
LivePagedListProvider<Integer, Contact> contactsByNameAndCryptoNet(String cryptoNet);
|
||||
|
||||
@Query("SELECT * FROM contact WHERE id = :id")
|
||||
LiveData<Contact> getById(long id);
|
||||
|
||||
|
@ -49,4 +53,7 @@ public interface ContactDao {
|
|||
|
||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||
public void updateAddressesFields(ContactAddress... contactAddresses);
|
||||
|
||||
@Delete
|
||||
public void deleteContacts(Contact... contacts);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.arch.paging.PagedList;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnItemSelected;
|
||||
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.ValidateBitsharesSendRequest;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
import cy.agorise.crystalwallet.viewmodels.ContactListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.SendTransactionValidator;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField;
|
||||
import cy.agorise.crystalwallet.views.ContactSelectionListAdapter;
|
||||
import cy.agorise.crystalwallet.views.CryptoCurrencyAdapter;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetAccountAdapter;
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||
|
||||
public class ContactSelectionFragment extends DialogFragment implements ContactSelectionListAdapter.ContactSelectionListAdapterListener{
|
||||
|
||||
private CryptoNet cryptoNet;
|
||||
private CrystalDatabase db;
|
||||
private AlertDialog.Builder builder;
|
||||
|
||||
@BindView(R.id.contactListView)
|
||||
RecyclerView contactSelectionListView;
|
||||
|
||||
public static ContactSelectionFragment newInstance(CryptoNet cryptoNet) {
|
||||
ContactSelectionFragment f = new ContactSelectionFragment();
|
||||
|
||||
// Supply num input as an argument.
|
||||
Bundle args = new Bundle();
|
||||
args.putString("CRYPTO_NET", cryptoNet.name());
|
||||
f.setArguments(args);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
//AlertDialog.Builder
|
||||
builder = new AlertDialog.Builder(getActivity(), R.style.SendTransactionTheme);
|
||||
|
||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
View view = inflater.inflate(R.layout.contact_list, null);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this.getContext());
|
||||
this.contactSelectionListView.setLayoutManager(linearLayoutManager);
|
||||
//Prevents the list to start again when scrolling to the end
|
||||
this.contactSelectionListView.setNestedScrollingEnabled(false);
|
||||
final ContactSelectionListAdapter contactSelectionListAdapter = new ContactSelectionListAdapter();
|
||||
contactSelectionListAdapter.setListener(this);
|
||||
contactSelectionListView.setAdapter(contactSelectionListAdapter);
|
||||
|
||||
this.cryptoNet = CryptoNet.valueOf(getArguments().getString("CRYPTO_NET"));
|
||||
if (this.cryptoNet != null) {
|
||||
ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class);
|
||||
contactListViewModel.init(this.cryptoNet);
|
||||
LiveData<PagedList<Contact>> contactsLiveData = contactListViewModel.getContactList();
|
||||
|
||||
contactsLiveData.observe(this, new Observer<PagedList<Contact>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable PagedList<Contact> contacts) {
|
||||
contactSelectionListAdapter.setList(contacts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return builder.setView(view).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactSelected(Contact contact) {
|
||||
Intent result = new Intent();
|
||||
result.putExtra("CONTACT_ID", contact.getId());
|
||||
getTargetFragment().onActivityResult(getTargetRequestCode(), 1, result);
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ public class ContactsFragment extends Fragment {
|
|||
ButterKnife.bind(this, v);
|
||||
|
||||
ContactListViewModel contactListViewModel = ViewModelProviders.of(this).get(ContactListViewModel.class);
|
||||
contactListViewModel.init();
|
||||
LiveData<PagedList<Contact>> contactsLiveData = contactListViewModel.getContactList();
|
||||
|
||||
contactsLiveData.observe(this, new Observer<PagedList<Contact>>() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.arch.lifecycle.LiveData;
|
|||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -12,6 +13,7 @@ import android.support.annotation.Nullable;
|
|||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
|
@ -23,8 +25,10 @@ import android.view.Window;
|
|||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
|
@ -41,10 +45,13 @@ import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestListen
|
|||
import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.cryptonetinforequests.ValidateBitsharesSendRequest;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
import cy.agorise.crystalwallet.models.ContactAddress;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
import cy.agorise.crystalwallet.viewmodels.ContactViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.SendTransactionValidator;
|
||||
|
@ -82,6 +89,8 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
FloatingActionButton btnSend;
|
||||
@BindView(R.id.btnCancel)
|
||||
TextView btnCancel;
|
||||
@BindView(R.id.ivPeople)
|
||||
ImageView ivPeople;
|
||||
|
||||
Button btnScanQrCode;
|
||||
|
||||
|
@ -222,6 +231,50 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
this.sendTransactionValidator.validate();
|
||||
}
|
||||
|
||||
@OnClick(R.id.ivPeople)
|
||||
public void searchContact(){
|
||||
FragmentTransaction ft = this.getActivity().getSupportFragmentManager().beginTransaction();
|
||||
Fragment prev = this.getActivity().getSupportFragmentManager().findFragmentByTag("ContactSelectionDialog");
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
ft.addToBackStack(null);
|
||||
|
||||
// Show a contact selection list
|
||||
ContactSelectionFragment contactSelectionFragment = ContactSelectionFragment.newInstance(this.cryptoNetAccount.getCryptoNet());
|
||||
contactSelectionFragment.setTargetFragment(this, 1);
|
||||
contactSelectionFragment.show(ft, "ContactSelectionDialog");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode,resultCode,data);
|
||||
|
||||
if(requestCode == 1) {
|
||||
if(resultCode == 1) {
|
||||
long contactId = data.getLongExtra("CONTACT_ID",-1);
|
||||
if (contactId > -1){
|
||||
ContactViewModel contactViewModel = ViewModelProviders.of(this).get(ContactViewModel.class);
|
||||
contactViewModel.init(contactId);
|
||||
LiveData<List<ContactAddress>> contactAddressesLiveData = contactViewModel.getContactAddresses();
|
||||
|
||||
contactAddressesLiveData.observe(this, new Observer<List<ContactAddress>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<ContactAddress> contactAddresses) {
|
||||
if (contactAddresses != null) {
|
||||
for (ContactAddress contactAddress : contactAddresses) {
|
||||
if (contactAddress.getCryptoNet() == cryptoNetAccount.getCryptoNet()) {
|
||||
etTo.setText(contactAddress.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnCancel)
|
||||
public void cancel(){
|
||||
this.dismiss();
|
||||
|
|
|
@ -13,6 +13,8 @@ import android.support.v7.recyclerview.extensions.DiffCallback;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
|
||||
/**
|
||||
* Represents a user contact
|
||||
*
|
||||
|
@ -85,6 +87,18 @@ public class Contact {
|
|||
address.setContactId(this.getId());
|
||||
}
|
||||
|
||||
public ContactAddress getCryptoNetAddress(CryptoNet cryptoNet){
|
||||
if (this.mAddresses != null) {
|
||||
for (ContactAddress address : this.mAddresses) {
|
||||
if (address.getCryptoNet() == cryptoNet) {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final DiffCallback<Contact> DIFF_CALLBACK = new DiffCallback<Contact>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.arch.lifecycle.LiveData;
|
|||
import android.arch.paging.PagedList;
|
||||
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
|
||||
|
@ -30,6 +31,26 @@ public class ContactListViewModel extends AndroidViewModel {
|
|||
);
|
||||
}
|
||||
|
||||
public void init(){
|
||||
contactList = this.db.contactDao().contactsByName().create(0,
|
||||
new PagedList.Config.Builder()
|
||||
.setEnablePlaceholders(true)
|
||||
.setPageSize(10)
|
||||
.setPrefetchDistance(10)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
public void init(CryptoNet cryptoNet){
|
||||
contactList = this.db.contactDao().contactsByNameAndCryptoNet(cryptoNet.name()).create(0,
|
||||
new PagedList.Config.Builder()
|
||||
.setEnablePlaceholders(true)
|
||||
.setPageSize(10)
|
||||
.setPrefetchDistance(10)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
public LiveData<PagedList<Contact>> getContactList(){
|
||||
return this.contactList;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
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.Contact;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 2/16/2018.
|
||||
*
|
||||
* An adapter to show the elements of a list of contacts to be selected by the user
|
||||
*/
|
||||
|
||||
public class ContactSelectionListAdapter extends ListAdapter<Contact, ContactSelectionViewHolder> implements ContactSelectionViewHolder.ContactSelectionViewHolderListener {
|
||||
|
||||
private ContactSelectionListAdapterListener listener;
|
||||
|
||||
public ContactSelectionListAdapter() {
|
||||
super(Contact.DIFF_CALLBACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactSelectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.contact_selection_list_item,parent,false);
|
||||
return new ContactSelectionViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ContactSelectionViewHolder holder, int position) {
|
||||
Contact contact = getItem(position);
|
||||
if (contact != null) {
|
||||
holder.bindTo(contact);
|
||||
holder.setListener(this);
|
||||
} else {
|
||||
holder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactSelected(ContactSelectionViewHolder contactSelectionViewHolder, Contact contact) {
|
||||
if (this.listener != null){
|
||||
this.listener.onContactSelected(contact);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(ContactSelectionListAdapterListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface ContactSelectionListAdapterListener{
|
||||
public void onContactSelected(Contact contact);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package cy.agorise.crystalwallet.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
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.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 2/16/2018.
|
||||
*
|
||||
* Represents an element view from the Contact Selection List
|
||||
*/
|
||||
|
||||
public class ContactSelectionViewHolder extends RecyclerView.ViewHolder {
|
||||
private TextView tvName;
|
||||
private ImageView ivThumbnail;
|
||||
private TextView tvLastPaid;
|
||||
private Context context;
|
||||
private ContactSelectionViewHolderListener listener;
|
||||
|
||||
public ContactSelectionViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
//TODO: use ButterKnife to load this
|
||||
tvName = (TextView) itemView.findViewById(R.id.tvContactName);
|
||||
ivThumbnail = (ImageView) itemView.findViewById(R.id.ivContactThumbnail);
|
||||
tvLastPaid = (TextView) itemView.findViewById(R.id.tvLastPaid);
|
||||
this.context = itemView.getContext();
|
||||
|
||||
}
|
||||
|
||||
public void setListener(ContactSelectionViewHolderListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clears the information in this element view
|
||||
*/
|
||||
public void clear(){
|
||||
tvName.setText("");
|
||||
ivThumbnail.setImageResource(android.R.color.transparent);
|
||||
tvLastPaid.setText("");
|
||||
}
|
||||
|
||||
/*
|
||||
* Binds this view with the data of an element of the list
|
||||
*/
|
||||
public void bindTo(final Contact contact) {
|
||||
if (contact == null){
|
||||
this.clear();
|
||||
} else {
|
||||
final ContactSelectionViewHolder thisViewHolder = this;
|
||||
|
||||
tvName.setText(contact.getName());
|
||||
tvLastPaid.setText("Paid: 1 Jan, 2001 01:01");
|
||||
|
||||
this.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (listener != null){
|
||||
listener.onContactSelected(thisViewHolder, contact);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public interface ContactSelectionViewHolderListener {
|
||||
public void onContactSelected(ContactSelectionViewHolder contactSelectionViewHolder, Contact contact);
|
||||
}
|
||||
}
|
39
app/src/main/res/layout/contact_selection_list_item.xml
Normal file
39
app/src/main/res/layout/contact_selection_list_item.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?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">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:id="@+id/ivContactThumbnail"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvContactName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/ivContactThumbnail"
|
||||
android:text="Loading name..."
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLastPaid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/tvContactName"
|
||||
android:layout_toRightOf="@+id/ivContactThumbnail"
|
||||
android:text="Paid: Jan 1, 2001, 01:01"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
Loading…
Reference in a new issue