Skip to content
Snippets Groups Projects
Commit 06d32814 authored by akwizgran's avatar akwizgran
Browse files

Show connection indicator and last connection time in contact list.

parent 330889a4
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,8 @@
<string name="contact_list_button">Contacts</string>
<string name="quit_button">Quit</string>
<string name="contact_list_title">Contacts</string>
<string name="contact_connected">Connected</string>
<string name="contact_last_connected">Last connected &lt;br /&gt; %s</string>
<string name="add_contact_button">Add a contact</string>
<string name="add_contact_title">Add a Contact</string>
<string name="same_network">Briar can add contacts via Wi-Fi or Bluetooth. For security reasons, you must be face-to-face to add someone as a contact. To use Wi-Fi you must both be connected to the same network.</string>
......
......@@ -20,8 +20,8 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ProgressBar;
import android.widget.RelativeLayout.LayoutParams;
public class HomeScreenActivity extends BriarActivity
implements OnClickListener {
......
......@@ -7,9 +7,7 @@ import static android.widget.LinearLayout.VERTICAL;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
......@@ -25,6 +23,7 @@ import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DatabaseExecutor;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.event.ContactAddedEvent;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.transport.ConnectionListener;
......@@ -37,8 +36,8 @@ import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.RelativeLayout.LayoutParams;
import com.google.inject.Inject;
......@@ -47,7 +46,6 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
private static final Logger LOG =
Logger.getLogger(ContactListActivity.class.getName());
private static final ItemComparator COMPARATOR = new ItemComparator();
private final BriarServiceConnection serviceConnection =
new BriarServiceConnection();
......@@ -67,10 +65,10 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
layout.setOrientation(VERTICAL);
layout.setGravity(CENTER_HORIZONTAL);
adapter = new ArrayAdapter<ContactListItem>(this,
android.R.layout.simple_expandable_list_item_1,
new ArrayList<ContactListItem>());
adapter = new ContactListAdapter(this);
ListView listView = new ListView(this);
listView.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT,
1f));
listView.setAdapter(adapter);
layout.addView(listView);
......@@ -85,14 +83,13 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
setContentView(layout);
// Listen for database events and connection events
// Listen for contacts being added or removed
db.addListener(this);
// Listen for contacts connecting or disconnecting
connectionRegistry.addListener(this);
// Bind to the service
// Bind to the service so we can wait for the DB to be opened
bindService(new Intent(BriarService.class.getName()),
serviceConnection, 0);
// Load the contact list from the DB
reloadContactList();
......@@ -105,9 +102,12 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
IBinder binder = serviceConnection.waitForBinder();
((BriarBinder) binder).getService().waitForStartup();
if(LOG.isLoggable(INFO)) LOG.info("Service started");
// Insert a couple of fake contacts
db.addContact("Alice");
db.addContact("Bob");
Collection<Contact> contacts = db.getContacts();
if(contacts.isEmpty()) {
// Insert a couple of fake contacts
db.addContact("Alice");
db.addContact("Bob");
}
} catch(DbException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
......@@ -134,6 +134,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
public void eventOccurred(DatabaseEvent e) {
if(e instanceof ContactAddedEvent) reloadContactList();
else if(e instanceof ContactRemovedEvent) reloadContactList();
}
private void reloadContactList() {
......@@ -148,11 +149,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
if(LOG.isLoggable(INFO))
LOG.info("Loaded " + contacts.size() + " contacts");
// Update the contact list
runOnUiThread(new Runnable() {
public void run() {
updateContactList(contacts);
}
});
updateContactList(contacts);
} catch(DbException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
......@@ -165,14 +162,17 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
});
}
// UI thread
private void updateContactList(Collection<Contact> contacts) {
adapter.clear();
for(Contact c : contacts) {
boolean connected = connectionRegistry.isConnected(c.getId());
adapter.add(new ContactListItem(c, connected));
}
adapter.sort(COMPARATOR);
private void updateContactList(final Collection<Contact> contacts) {
runOnUiThread(new Runnable() {
public void run() {
adapter.clear();
for(Contact c : contacts) {
boolean conn = connectionRegistry.isConnected(c.getId());
adapter.add(new ContactListItem(c, conn));
}
adapter.sort(ContactListItem.COMPARATOR);
}
});
}
public void contactConnected(final ContactId c) {
......@@ -189,37 +189,12 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
int count = adapter.getCount();
for(int i = 0; i < count; i++) {
ContactListItem item = adapter.getItem(i);
if(item.contact.getId().equals(c)) {
item.connected = connected;
if(item.getContactId().equals(c)) {
item.setConnected(connected);
return;
}
}
}
});
}
private static class ItemComparator implements Comparator<ContactListItem> {
@Override
public int compare(ContactListItem a, ContactListItem b) {
return String.CASE_INSENSITIVE_ORDER.compare(a.contact.getName(),
b.contact.getName());
}
}
private static class ContactListItem {
private final Contact contact;
private boolean connected; // UI thread
private ContactListItem(Contact contact, boolean connected) {
this.contact = contact;
this.connected = connected;
}
@Override
public String toString() {
return contact.getName() + " (" + connected + ")";
}
}
}
package net.sf.briar.android.contact;
import static android.view.Gravity.CENTER;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.widget.LinearLayout.HORIZONTAL;
import java.util.ArrayList;
import net.sf.briar.R;
import android.content.Context;
import android.text.Html;
import android.text.format.DateUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
public class ContactListAdapter extends ArrayAdapter<ContactListItem> {
public ContactListAdapter(Context context) {
super(context, android.R.layout.simple_expandable_list_item_1,
new ArrayList<ContactListItem>());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ContactListItem item = getItem(position);
Context ctx = getContext();
LinearLayout layout = new LinearLayout(ctx);
layout.setOrientation(HORIZONTAL);
layout.setGravity(CENTER);
ImageView bulb = new ImageView(ctx);
if(item.getConnected()) bulb.setImageResource(R.drawable.green_bulb);
else bulb.setImageResource(R.drawable.grey_bulb);
bulb.setPadding(5, 0, 5, 0);
layout.addView(bulb);
TextView name = new TextView(ctx);
name.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f));
name.setTextSize(18);
name.setText(item.getName());
layout.addView(name);
TextView connected = new TextView(ctx);
connected.setTextSize(12);
connected.setPadding(5, 0, 5, 0);
if(item.getConnected()) {
connected.setText(R.string.contact_connected);
} else {
String format = ctx.getResources().getString(
R.string.contact_last_connected);
long then = item.getLastConnected();
CharSequence ago = DateUtils.getRelativeTimeSpanString(then);
connected.setText(Html.fromHtml(String.format(format, ago)));
}
layout.addView(connected);
return layout;
}
}
package net.sf.briar.android.contact;
import java.util.Comparator;
import net.sf.briar.api.Contact;
import net.sf.briar.api.ContactId;
// This class is not thread-safe
class ContactListItem {
static Comparator<ContactListItem> COMPARATOR = new ItemComparator();
private final Contact contact;
private boolean connected;
ContactListItem(Contact contact, boolean connected) {
this.contact = contact;
this.connected = connected;
}
ContactId getContactId() {
return contact.getId();
}
String getName() {
return contact.getName();
}
long getLastConnected() {
return contact.getLastConnected();
}
boolean getConnected() {
return connected;
}
void setConnected(boolean connected) {
this.connected = connected;
}
private static class ItemComparator implements Comparator<ContactListItem> {
@Override
public int compare(ContactListItem a, ContactListItem b) {
return String.CASE_INSENSITIVE_ORDER.compare(a.contact.getName(),
b.contact.getName());
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment