diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index b57845c6b..5e9dfba96 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -47,6 +47,7 @@
From:
To:
(Anonymous)
+ New contact\u2026
Groups
(No posts)
New Group
diff --git a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java
index 84ec78b6c..e62dff274 100644
--- a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java
+++ b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java
@@ -24,7 +24,7 @@ import net.sf.briar.R;
import net.sf.briar.android.BriarFragmentActivity;
import net.sf.briar.android.BriarService;
import net.sf.briar.android.BriarService.BriarServiceConnection;
-import net.sf.briar.android.SelectContactsDialog;
+import net.sf.briar.android.contact.SelectContactsDialog;
import net.sf.briar.android.invitation.AddContactActivity;
import net.sf.briar.android.messages.NoContactsDialog;
import net.sf.briar.api.Contact;
diff --git a/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java
index c4cf025cb..c0ee80065 100644
--- a/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java
+++ b/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java
@@ -34,7 +34,7 @@ class LocalGroupSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
}
public int getCount() {
- return list.size() + 1;
+ return list.isEmpty() ? 0 : list.size() + 1;
}
@Override
@@ -67,7 +67,7 @@ class LocalGroupSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
@Override
public boolean isEmpty() {
- return getCount() == 0;
+ return list.isEmpty();
}
public void sort(Comparator comparator) {
diff --git a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java
index 57dfded06..cae099277 100644
--- a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java
+++ b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java
@@ -99,7 +99,7 @@ implements OnItemSelectedListener, OnClickListener {
TextView from = new TextView(this);
from.setTextSize(18);
- from.setPadding(10, 10, 10, 10);
+ from.setPadding(10, 10, 0, 10);
from.setText(R.string.from);
header.addView(from);
diff --git a/briar-android/src/net/sf/briar/android/contact/ContactItem.java b/briar-android/src/net/sf/briar/android/contact/ContactItem.java
new file mode 100644
index 000000000..7d6f0dc02
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/contact/ContactItem.java
@@ -0,0 +1,18 @@
+package net.sf.briar.android.contact;
+
+import net.sf.briar.api.Contact;
+
+public class ContactItem {
+
+ public static final ContactItem NEW = new ContactItem(null);
+
+ private final Contact contact;
+
+ public ContactItem(Contact contact) {
+ this.contact = contact;
+ }
+
+ public Contact getContact() {
+ return contact;
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/contact/ContactNameComparator.java b/briar-android/src/net/sf/briar/android/contact/ContactNameComparator.java
new file mode 100644
index 000000000..bb8bb09a6
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/contact/ContactNameComparator.java
@@ -0,0 +1,18 @@
+package net.sf.briar.android.contact;
+
+import java.util.Comparator;
+
+public class ContactNameComparator implements Comparator {
+
+ public static final ContactNameComparator INSTANCE =
+ new ContactNameComparator();
+
+ public int compare(ContactItem a, ContactItem b) {
+ if(a == b) return 0;
+ if(a == ContactItem.NEW) return 1;
+ if(b == ContactItem.NEW) return -1;
+ String aName = a.getContact().getAuthor().getName();
+ String bName = b.getContact().getAuthor().getName();
+ return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/contact/ContactSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/contact/ContactSpinnerAdapter.java
new file mode 100644
index 000000000..58e17c02d
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/contact/ContactSpinnerAdapter.java
@@ -0,0 +1,77 @@
+package net.sf.briar.android.contact;
+
+import static net.sf.briar.android.contact.ContactItem.NEW;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import net.sf.briar.R;
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+public class ContactSpinnerAdapter extends BaseAdapter
+implements SpinnerAdapter {
+
+ private final Context ctx;
+ private final List list = new ArrayList();
+
+ public ContactSpinnerAdapter(Context ctx) {
+ this.ctx = ctx;
+ }
+
+ public void add(ContactItem item) {
+ list.add(item);
+ }
+
+ public void clear() {
+ list.clear();
+ }
+
+ public int getCount() {
+ return list.isEmpty() ? 0 : list.size() + 1;
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView,
+ ViewGroup parent) {
+ return getView(position, convertView, parent);
+ }
+
+ public ContactItem getItem(int position) {
+ if(position == list.size()) return NEW;
+ return list.get(position);
+ }
+
+ public long getItemId(int position) {
+ return android.R.layout.simple_spinner_item;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView name = new TextView(ctx);
+ name.setTextSize(18);
+ name.setMaxLines(1);
+ Resources res = ctx.getResources();
+ int pad = res.getInteger(R.integer.spinner_padding);
+ name.setPadding(pad, pad, pad, pad);
+ ContactItem item = getItem(position);
+ if(item == NEW) name.setText(R.string.new_contact_item);
+ else name.setText(item.getContact().getAuthor().getName());
+ return name;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return list.isEmpty();
+ }
+
+ public void sort(Comparator comparator) {
+ Collections.sort(list, comparator);
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/SelectContactsDialog.java b/briar-android/src/net/sf/briar/android/contact/SelectContactsDialog.java
similarity index 98%
rename from briar-android/src/net/sf/briar/android/SelectContactsDialog.java
rename to briar-android/src/net/sf/briar/android/contact/SelectContactsDialog.java
index 6a07376b2..ffbd584b6 100644
--- a/briar-android/src/net/sf/briar/android/SelectContactsDialog.java
+++ b/briar-android/src/net/sf/briar/android/contact/SelectContactsDialog.java
@@ -1,4 +1,4 @@
-package net.sf.briar.android;
+package net.sf.briar.android.contact;
import java.util.Collection;
import java.util.HashSet;
diff --git a/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java b/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java
index 57b280767..028d0cccd 100644
--- a/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java
@@ -23,7 +23,7 @@ import net.sf.briar.R;
import net.sf.briar.android.BriarFragmentActivity;
import net.sf.briar.android.BriarService;
import net.sf.briar.android.BriarService.BriarServiceConnection;
-import net.sf.briar.android.SelectContactsDialog;
+import net.sf.briar.android.contact.SelectContactsDialog;
import net.sf.briar.android.invitation.AddContactActivity;
import net.sf.briar.android.messages.NoContactsDialog;
import net.sf.briar.api.Contact;
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupSpinnerAdapter.java
index c4180324b..ff027ac97 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupSpinnerAdapter.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupSpinnerAdapter.java
@@ -34,7 +34,7 @@ class GroupSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
}
public int getCount() {
- return list.size() + 1;
+ return list.isEmpty() ? 0 : list.size() + 1;
}
@Override
@@ -67,7 +67,7 @@ class GroupSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
@Override
public boolean isEmpty() {
- return getCount() == 0;
+ return list.isEmpty();
}
public void sort(Comparator comparator) {
diff --git a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java
index 7fb542d74..3254c70c2 100644
--- a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java
@@ -102,7 +102,7 @@ implements OnItemSelectedListener, OnClickListener {
TextView from = new TextView(this);
from.setTextSize(18);
- from.setPadding(10, 10, 10, 10);
+ from.setPadding(10, 10, 0, 10);
from.setText(R.string.from);
header.addView(from);
diff --git a/briar-android/src/net/sf/briar/android/identity/LocalAuthorSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/identity/LocalAuthorSpinnerAdapter.java
index 493653d4d..0f000a224 100644
--- a/briar-android/src/net/sf/briar/android/identity/LocalAuthorSpinnerAdapter.java
+++ b/briar-android/src/net/sf/briar/android/identity/LocalAuthorSpinnerAdapter.java
@@ -38,6 +38,7 @@ implements SpinnerAdapter {
}
public int getCount() {
+ if(list.isEmpty()) return 0;
return includeAnonymous ? list.size() + 2 : list.size() + 1;
}
@@ -78,7 +79,7 @@ implements SpinnerAdapter {
@Override
public boolean isEmpty() {
- return getCount() == 0;
+ return list.isEmpty();
}
public void sort(Comparator comparator) {
diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java
index 6f59e7413..c4fc69b0a 100644
--- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java
+++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java
@@ -214,6 +214,7 @@ implements InvitationListener {
final Collection localAuthors) {
runOnUiThread(new Runnable() {
public void run() {
+ if(localAuthors.isEmpty()) throw new IllegalStateException();
adapter.clear();
for(LocalAuthor a : localAuthors)
adapter.add(new LocalAuthorItem(a));
diff --git a/briar-android/src/net/sf/briar/android/messages/ContactSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/messages/ContactSpinnerAdapter.java
deleted file mode 100644
index 79bc800b7..000000000
--- a/briar-android/src/net/sf/briar/android/messages/ContactSpinnerAdapter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package net.sf.briar.android.messages;
-
-import java.util.ArrayList;
-
-import net.sf.briar.R;
-import net.sf.briar.api.Contact;
-import android.content.Context;
-import android.content.res.Resources;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.SpinnerAdapter;
-import android.widget.TextView;
-
-public class ContactSpinnerAdapter extends ArrayAdapter
-implements SpinnerAdapter {
-
- ContactSpinnerAdapter(Context context) {
- super(context, android.R.layout.simple_spinner_item,
- new ArrayList());
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- TextView name = new TextView(getContext());
- name.setTextSize(18);
- name.setMaxLines(1);
- Resources res = getContext().getResources();
- int pad = res.getInteger(R.integer.spinner_padding);
- name.setPadding(pad, pad, pad, pad);
- name.setText(getItem(position).getAuthor().getName());
- return name;
- }
-
- @Override
- public View getDropDownView(int position, View convertView,
- ViewGroup parent) {
- return getView(position, convertView, parent);
- }
-}
diff --git a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java
index 0ddfced47..09a5a263d 100644
--- a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java
@@ -20,6 +20,10 @@ import net.sf.briar.R;
import net.sf.briar.android.BriarActivity;
import net.sf.briar.android.BriarService;
import net.sf.briar.android.BriarService.BriarServiceConnection;
+import net.sf.briar.android.contact.ContactItem;
+import net.sf.briar.android.contact.ContactNameComparator;
+import net.sf.briar.android.contact.ContactSpinnerAdapter;
+import net.sf.briar.android.invitation.AddContactActivity;
import net.sf.briar.android.widgets.HorizontalSpace;
import net.sf.briar.api.AuthorId;
import net.sf.briar.api.Contact;
@@ -174,12 +178,19 @@ implements OnItemSelectedListener, OnClickListener {
runOnUiThread(new Runnable() {
public void run() {
if(contacts.isEmpty()) finish();
- int index = -1;
- for(Contact c : contacts) {
- if(c.getId().equals(contactId)) index = adapter.getCount();
- adapter.add(c);
+ adapter.clear();
+ for(Contact c : contacts) adapter.add(new ContactItem(c));
+ adapter.sort(ContactNameComparator.INSTANCE);
+ adapter.notifyDataSetChanged();
+ int count = adapter.getCount();
+ for(int i = 0; i < count; i++) {
+ ContactItem item = adapter.getItem(i);
+ if(item == ContactItem.NEW) continue;
+ if(item.getContact().getId().equals(contactId)) {
+ spinner.setSelection(i);
+ break;
+ }
}
- if(index != -1) spinner.setSelection(index);
}
});
}
@@ -199,9 +210,14 @@ implements OnItemSelectedListener, OnClickListener {
public void onItemSelected(AdapterView> parent, View view, int position,
long id) {
- Contact c = adapter.getItem(position);
- loadLocalAuthor(c.getLocalAuthorId());
- contactId = c.getId();
+ ContactItem item = adapter.getItem(position);
+ if(item == ContactItem.NEW) {
+ startActivity(new Intent(this, AddContactActivity.class));
+ } else {
+ Contact c = item.getContact();
+ loadLocalAuthor(c.getLocalAuthorId());
+ contactId = c.getId();
+ }
}
private void loadLocalAuthor(final AuthorId a) {