diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index b57845c6b6a82241654d6d9dc0d71ae5588f03e6..5e9dfba96c03d8eeda6b1db194ff7d36035de898 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -47,6 +47,7 @@ <string name="from">From:</string> <string name="to">To:</string> <string name="anonymous">(Anonymous)</string> + <string name="new_contact_item">New contact\u2026</string> <string name="groups_title">Groups</string> <string name="no_posts">(No posts)</string> <string name="create_group_title">New Group</string> 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 84ec78b6ce8e9c0ce7b53149e279a1fe7fd8dee9..e62dff274a37f50f31a6d4e3d91beb5ec80752aa 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 c4cf025cb874cdf8218b31ac76008c3a2ea124b7..c0ee80065dcb0c67bd70ecb265249536e9ec4959 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<LocalGroupItem> 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 57dfded067bcfc6221bab347e0c563e4505aa700..cae099277cc28873cd064397475d9febd1ef859d 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 0000000000000000000000000000000000000000..7d6f0dc0201e15369d35c9c6620f5c009a2f4675 --- /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 0000000000000000000000000000000000000000..bb8bb09a62b2b6fd602c51564c07bfa88783862d --- /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<ContactItem> { + + 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 0000000000000000000000000000000000000000..58e17c02d22ec335c6e6649c77334e425c99e40d --- /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<ContactItem> list = new ArrayList<ContactItem>(); + + 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<ContactItem> 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 6a07376b22e8875900a810f2198182b050116c2b..ffbd584b60b644f4188e5290cc8d17da9b874996 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 57b280767b907f1fe916cce022584bd5c582fb22..028d0cccd93f5eb95dd134afbe7fbf1a5694d926 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 c4180324b9c977e5d5229b8219c8cfb5414e1d7f..ff027ac971c513e82ee8e548a69342f0bd2089c7 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<GroupItem> 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 7fb542d741d8cfc19de3c23387f2b916993a7d38..3254c70c2e38cdd92e4ba685bc9436734f5d1946 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 493653d4d4e3defa1bf4028a20819e4bdd124267..0f000a224b6b2c10301bdc0ea868cf41cd23b570 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<LocalAuthorItem> 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 6f59e7413a020bb728e86a5d805356304d5406d5..c4fc69b0ab24568027abf755bab407033a1a6a6d 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<LocalAuthor> 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 79bc800b78d484756aada7ca9d3b128fb4e5f606..0000000000000000000000000000000000000000 --- 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<Contact> -implements SpinnerAdapter { - - ContactSpinnerAdapter(Context context) { - super(context, android.R.layout.simple_spinner_item, - new ArrayList<Contact>()); - } - - @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 0ddfced47472ef1f12f999ea2c90c76bc388000a..09a5a263dc5b8882fba0b257a1d846141c92e742 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) {