diff --git a/briar-android/res/layout/activity_contact_list.xml b/briar-android/res/layout/activity_contact_list.xml index 02faeff9b..333dac203 100644 --- a/briar-android/res/layout/activity_contact_list.xml +++ b/briar-android/res/layout/activity_contact_list.xml @@ -1,54 +1,28 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent"/> - - - - - - - + android:layout_gravity="bottom|end" + android:layout_margin="@dimen/margin_activity_horizontal" + android:src="@drawable/ic_add_white" + app:fabSize="normal" + app:elevation="4dp" + app:layout_anchor="@id/contactList" + app:layout_anchorGravity="bottom|right|end" + app:layout_behavior="org.briarproject.android.util.HideFabOnScrollBehavior"/> - - - \ No newline at end of file + diff --git a/briar-android/res/layout/briar_recycler_view.xml b/briar-android/res/layout/briar_recycler_view.xml new file mode 100644 index 000000000..d84769f3e --- /dev/null +++ b/briar-android/res/layout/briar_recycler_view.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 0a7c7b1f0..db7f2bfc4 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -128,4 +128,5 @@ Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ? Confirm Contact Deletion Are you sure that you want to remove this contact and all messages exchanged with this contact? + No data diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java index b3fec8962..791883254 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java @@ -4,15 +4,12 @@ import android.content.Intent; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.View; -import android.view.View.OnCreateContextMenuListener; -import android.widget.ProgressBar; -import android.widget.TextView; import org.briarproject.R; import org.briarproject.android.BriarActivity; import org.briarproject.android.invitation.AddContactActivity; +import org.briarproject.android.util.BriarRecyclerView; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; @@ -38,22 +35,18 @@ import java.util.logging.Logger; import javax.inject.Inject; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; public class ContactListActivity extends BriarActivity - implements OnCreateContextMenuListener, EventListener { + implements EventListener { private static final Logger LOG = Logger.getLogger(ContactListActivity.class.getName()); @Inject private ConnectionRegistry connectionRegistry; - private TextView empty = null; private ContactListAdapter adapter = null; - private RecyclerView list = null; - private ProgressBar loading = null; + private BriarRecyclerView list = null; // Fields that are accessed from background threads must be volatile @Inject private volatile ContactManager contactManager; @@ -67,18 +60,10 @@ public class ContactListActivity extends BriarActivity setContentView(R.layout.activity_contact_list); adapter = new ContactListAdapter(this); - list = (RecyclerView) findViewById(R.id.contactList); + list = (BriarRecyclerView) findViewById(R.id.contactList); list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); - list.setOnCreateContextMenuListener(this); - list.setVisibility(GONE); - - // Show a notice when there are no contacts - empty = (TextView) findViewById(R.id.emptyView); - - // Show a progress bar while the list is loading - loading = (ProgressBar) findViewById(R.id.progressBar); - loading.setVisibility(VISIBLE); + list.setEmptyText(getString(R.string.no_contacts)); // Show a floating action button FloatingActionButton fab = (FloatingActionButton) findViewById( @@ -104,18 +89,12 @@ public class ContactListActivity extends BriarActivity public void onResume() { super.onResume(); eventBus.addListener(this); + loadContacts(); } private void loadContacts() { - runOnUiThread(new Runnable() { - public void run() { - empty.setVisibility(GONE); - list.setVisibility(GONE); - loading.setVisibility(VISIBLE); - } - }); runOnDbThread(new Runnable() { public void run() { try { @@ -155,15 +134,11 @@ public class ContactListActivity extends BriarActivity runOnUiThread(new Runnable() { public void run() { if (contacts.size() > 0) { - list.setVisibility(VISIBLE); - empty.setVisibility(GONE); + adapter.addAll(contacts); } else { - list.setVisibility(GONE); - empty.setVisibility(VISIBLE); + // no contacts to display, make sure progress bar is hidden + list.showData(); } - loading.setVisibility(GONE); - - adapter.addAll(contacts); } }); } @@ -228,11 +203,6 @@ public class ContactListActivity extends BriarActivity ContactListItem item = adapter.findItem(c); if (item != null) { adapter.remove(item); - - if (adapter.isEmpty()) { - empty.setVisibility(VISIBLE); - list.setVisibility(GONE); - } } } }); diff --git a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java new file mode 100644 index 000000000..4e50c1d5d --- /dev/null +++ b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java @@ -0,0 +1,119 @@ +package org.briarproject.android.util; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import org.briarproject.R; + +public class BriarRecyclerView extends FrameLayout { + + private RecyclerView recyclerView; + private TextView emptyView; + private ProgressBar progressBar; + private RecyclerView.AdapterDataObserver emptyObserver; + + public BriarRecyclerView(Context context) { + super(context); + + initViews(); + } + + public BriarRecyclerView(Context context, AttributeSet attrs) { + super(context, attrs); + + initViews(); + } + + public BriarRecyclerView(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + + initViews(); + } + + private void initViews() { + if (isInEditMode()) { + return; + } + + View v = LayoutInflater.from(getContext()).inflate( + R.layout.briar_recycler_view, this, true); + + recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView); + emptyView = (TextView) v.findViewById(R.id.emptyView); + progressBar = (ProgressBar) v.findViewById(R.id.progressBar); + + showProgressBar(); + + emptyObserver = new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + showData(); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + super.onItemRangeInserted(positionStart, itemCount); + onChanged(); + } + }; + } + + public void setLayoutManager(RecyclerView.LayoutManager layout) { + recyclerView.setLayoutManager(layout); + } + + public void setAdapter(RecyclerView.Adapter adapter) { + RecyclerView.Adapter oldAdapter = recyclerView.getAdapter(); + if (oldAdapter != null) { + oldAdapter.unregisterAdapterDataObserver(emptyObserver); + } + + recyclerView.setAdapter(adapter); + + if (adapter != null) { + adapter.registerAdapterDataObserver(emptyObserver); + + if (adapter.getItemCount() > 0) { + // only show data if adapter has data already + // otherwise progress bar is shown + emptyObserver.onChanged(); + } + } + } + + public void setEmptyText(String text) { + emptyView.setText(text); + } + + public void showProgressBar() { + recyclerView.setVisibility(View.INVISIBLE); + emptyView.setVisibility(View.INVISIBLE); + progressBar.setVisibility(View.VISIBLE); + } + + public void showData() { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter != null) { + if (adapter.getItemCount() == 0) { + emptyView.setVisibility(View.VISIBLE); + recyclerView.setVisibility(View.INVISIBLE); + } else { + emptyView.setVisibility(View.INVISIBLE); + recyclerView.setVisibility(View.VISIBLE); + } + progressBar.setVisibility(View.INVISIBLE); + } + } + + public RecyclerView getRecyclerView() { + return recyclerView; + } + +}