diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index f7362082d..9512c8e2d 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -9,6 +9,7 @@
Blogs
Synchronize
Quit
+ New identity\u2026
Contacts
Connected
Last connected <br /> %1$s
diff --git a/briar-android/src/net/sf/briar/android/AuthorNameComparator.java b/briar-android/src/net/sf/briar/android/AuthorNameComparator.java
deleted file mode 100644
index acde1829d..000000000
--- a/briar-android/src/net/sf/briar/android/AuthorNameComparator.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.sf.briar.android;
-
-import java.util.Comparator;
-
-import net.sf.briar.api.Author;
-
-public class AuthorNameComparator implements Comparator {
-
- public static final AuthorNameComparator INSTANCE =
- new AuthorNameComparator();
-
- public int compare(Author a1, Author a2) {
- return String.CASE_INSENSITIVE_ORDER.compare(a1.getName(),
- a2.getName());
- }
-}
diff --git a/briar-android/src/net/sf/briar/android/LocalAuthorItem.java b/briar-android/src/net/sf/briar/android/LocalAuthorItem.java
new file mode 100644
index 000000000..0e2d63c09
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/LocalAuthorItem.java
@@ -0,0 +1,19 @@
+package net.sf.briar.android;
+
+import net.sf.briar.api.LocalAuthor;
+
+public class LocalAuthorItem {
+
+ public static final LocalAuthorItem ANONYMOUS = new LocalAuthorItem(null);
+ public static final LocalAuthorItem NEW = new LocalAuthorItem(null);
+
+ private final LocalAuthor localAuthor;
+
+ public LocalAuthorItem(LocalAuthor localAuthor) {
+ this.localAuthor = localAuthor;
+ }
+
+ public LocalAuthor getLocalAuthor() {
+ return localAuthor;
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/LocalAuthorItemComparator.java b/briar-android/src/net/sf/briar/android/LocalAuthorItemComparator.java
new file mode 100644
index 000000000..c9ce0a1b0
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/LocalAuthorItemComparator.java
@@ -0,0 +1,21 @@
+package net.sf.briar.android;
+
+import static net.sf.briar.android.LocalAuthorItem.ANONYMOUS;
+import static net.sf.briar.android.LocalAuthorItem.NEW;
+
+import java.util.Comparator;
+
+public class LocalAuthorItemComparator implements Comparator {
+
+ public static final LocalAuthorItemComparator INSTANCE =
+ new LocalAuthorItemComparator();
+
+ public int compare(LocalAuthorItem a, LocalAuthorItem b) {
+ if(a == b) return 0;
+ if(a == ANONYMOUS || b == NEW) return -1;
+ if(a == NEW || b == ANONYMOUS) return 1;
+ String aName = a.getLocalAuthor().getName();
+ String bName = b.getLocalAuthor().getName();
+ return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java
index 668c5a427..b112a4056 100644
--- a/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java
+++ b/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java
@@ -1,35 +1,44 @@
package net.sf.briar.android;
+import static net.sf.briar.android.LocalAuthorItem.ANONYMOUS;
+import static net.sf.briar.android.LocalAuthorItem.NEW;
+
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import net.sf.briar.R;
-import net.sf.briar.api.LocalAuthor;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
-public class LocalAuthorSpinnerAdapter extends ArrayAdapter
+public class LocalAuthorSpinnerAdapter extends BaseAdapter
implements SpinnerAdapter {
- public LocalAuthorSpinnerAdapter(Context ctx) {
- super(ctx, android.R.layout.simple_spinner_item,
- new ArrayList());
+ private final Context ctx;
+ private final boolean includeAnonymous;
+ private final List list = new ArrayList();
+
+ public LocalAuthorSpinnerAdapter(Context ctx, boolean includeAnonymous) {
+ this.ctx = ctx;
+ this.includeAnonymous = includeAnonymous;
}
- @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).getName());
- return name;
+ public void add(LocalAuthorItem item) {
+ list.add(item);
+ }
+
+ public void clear() {
+ list.clear();
+ }
+
+ public int getCount() {
+ return includeAnonymous ? list.size() + 2 : list.size() + 1;
}
@Override
@@ -37,4 +46,42 @@ implements SpinnerAdapter {
ViewGroup parent) {
return getView(position, convertView, parent);
}
+
+ public LocalAuthorItem getItem(int position) {
+ if(includeAnonymous) {
+ if(position == 0) return ANONYMOUS;
+ if(position == list.size() + 1) return NEW;
+ return list.get(position - 1);
+ } else {
+ 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);
+ LocalAuthorItem item = getItem(position);
+ if(item == ANONYMOUS) name.setText(R.string.anonymous);
+ else if(item == NEW) name.setText(R.string.new_identity_item);
+ else name.setText(item.getLocalAuthor().getName());
+ return name;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return getCount() == 0;
+ }
+
+ public void sort(Comparator comparator) {
+ Collections.sort(list, comparator);
+ }
}
diff --git a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
index b205c5a20..b5f83046a 100644
--- a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
+++ b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
@@ -139,6 +139,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
adapter.add(new ContactListItem(c, conn));
}
adapter.sort(ContactComparator.INSTANCE);
+ adapter.notifyDataSetChanged();
}
});
}
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
index 893442a6a..289c85c59 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
@@ -142,6 +142,7 @@ OnClickListener, OnItemClickListener {
adapter.clear();
for(GroupMessageHeader h : headers) adapter.add(h);
adapter.sort(AscendingHeaderComparator.INSTANCE);
+ adapter.notifyDataSetChanged();
selectFirstUnread();
}
});
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
index 6759acba8..45d08d452 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
@@ -174,6 +174,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
adapter.add(new GroupListItem(g, headerList));
adapter.sort(GroupComparator.INSTANCE);
}
+ adapter.notifyDataSetChanged();
selectFirstUnread();
}
});
diff --git a/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java b/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java
index 0f1f6648d..4f7f2ff08 100644
--- a/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java
@@ -7,6 +7,8 @@ import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
+import static net.sf.briar.android.LocalAuthorItem.ANONYMOUS;
+import static net.sf.briar.android.LocalAuthorItem.NEW;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP;
import java.io.IOException;
@@ -20,11 +22,13 @@ import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.sf.briar.R;
-import net.sf.briar.android.AuthorNameComparator;
import net.sf.briar.android.BriarActivity;
import net.sf.briar.android.BriarService;
import net.sf.briar.android.BriarService.BriarServiceConnection;
+import net.sf.briar.android.LocalAuthorItem;
+import net.sf.briar.android.LocalAuthorItemComparator;
import net.sf.briar.android.LocalAuthorSpinnerAdapter;
+import net.sf.briar.android.identity.CreateIdentityActivity;
import net.sf.briar.android.widgets.HorizontalSpace;
import net.sf.briar.api.LocalAuthor;
import net.sf.briar.api.android.BundleEncrypter;
@@ -103,7 +107,7 @@ implements OnItemSelectedListener, OnClickListener {
from.setText(R.string.from);
header.addView(from);
- fromAdapter = new LocalAuthorSpinnerAdapter(this);
+ fromAdapter = new LocalAuthorSpinnerAdapter(this, true);
fromSpinner = new Spinner(this);
fromSpinner.setAdapter(fromAdapter);
fromSpinner.setOnItemSelectedListener(this);
@@ -126,7 +130,7 @@ implements OnItemSelectedListener, OnClickListener {
TextView to = new TextView(this);
to.setTextSize(18);
- to.setPadding(10, 10, 10, 10);
+ to.setPadding(10, 0, 0, 10);
to.setText(R.string.to);
header.addView(to);
@@ -188,8 +192,10 @@ implements OnItemSelectedListener, OnClickListener {
runOnUiThread(new Runnable() {
public void run() {
fromAdapter.clear();
- for(LocalAuthor a : localAuthors) fromAdapter.add(a);
- fromAdapter.sort(AuthorNameComparator.INSTANCE);
+ for(LocalAuthor a : localAuthors)
+ fromAdapter.add(new LocalAuthorItem(a));
+ fromAdapter.sort(LocalAuthorItemComparator.INSTANCE);
+ fromAdapter.notifyDataSetChanged();
}
});
}
@@ -256,7 +262,15 @@ implements OnItemSelectedListener, OnClickListener {
public void onItemSelected(AdapterView> parent, View view, int position,
long id) {
if(parent == fromSpinner) {
- localAuthor = fromAdapter.getItem(position);
+ LocalAuthorItem item = fromAdapter.getItem(position);
+ if(item == ANONYMOUS) {
+ localAuthor = null;
+ } else if(item == NEW) {
+ localAuthor = null;
+ startActivity(new Intent(this, CreateIdentityActivity.class));
+ } else {
+ localAuthor = item.getLocalAuthor();
+ }
} else if(parent == toSpinner) {
group = toAdapter.getItem(position);
groupId = group.getId();
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 07cd6e9da..e07efb08f 100644
--- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java
+++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java
@@ -7,10 +7,11 @@ import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
-import net.sf.briar.android.AuthorNameComparator;
import net.sf.briar.android.BriarActivity;
import net.sf.briar.android.BriarService;
import net.sf.briar.android.BriarService.BriarServiceConnection;
+import net.sf.briar.android.LocalAuthorItem;
+import net.sf.briar.android.LocalAuthorItemComparator;
import net.sf.briar.android.LocalAuthorSpinnerAdapter;
import net.sf.briar.api.AuthorId;
import net.sf.briar.api.LocalAuthor;
@@ -214,8 +215,10 @@ implements InvitationListener {
runOnUiThread(new Runnable() {
public void run() {
adapter.clear();
- for(LocalAuthor a : localAuthors) adapter.add(a);
- adapter.sort(AuthorNameComparator.INSTANCE);
+ for(LocalAuthor a : localAuthors)
+ adapter.add(new LocalAuthorItem(a));
+ adapter.sort(LocalAuthorItemComparator.INSTANCE);
+ adapter.notifyDataSetChanged();
}
});
}
diff --git a/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java b/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java
index 2a150f0a0..ddd2ac6d6 100644
--- a/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java
+++ b/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java
@@ -1,12 +1,16 @@
package net.sf.briar.android.invitation;
import static android.view.Gravity.CENTER;
+import static net.sf.briar.android.LocalAuthorItem.NEW;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP;
import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP;
import net.sf.briar.R;
+import net.sf.briar.android.LocalAuthorItem;
import net.sf.briar.android.LocalAuthorSpinnerAdapter;
+import net.sf.briar.android.identity.CreateIdentityActivity;
import net.sf.briar.api.AuthorId;
import android.content.Context;
+import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
@@ -43,7 +47,7 @@ OnClickListener {
yourNickname.setText(R.string.your_nickname);
innerLayout.addView(yourNickname);
- adapter = new LocalAuthorSpinnerAdapter(ctx);
+ adapter = new LocalAuthorSpinnerAdapter(ctx, false);
spinner = new Spinner(ctx);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
@@ -90,13 +94,20 @@ OnClickListener {
AuthorId localAuthorId = container.getLocalAuthorId();
boolean useBluetooth = container.getUseBluetooth();
String networkName = container.getNetworkName();
- continueButton.setEnabled(localAuthorId != null &&
- (useBluetooth || networkName != null));
+ boolean networkAvailable = useBluetooth || networkName != null;
+ continueButton.setEnabled(localAuthorId != null && networkAvailable);
}
public void onItemSelected(AdapterView> parent, View view, int position,
long id) {
- container.setLocalAuthorId(adapter.getItem(position).getId());
+ LocalAuthorItem item = adapter.getItem(position);
+ if(item == NEW) {
+ container.setLocalAuthorId(null);
+ Intent i = new Intent(container, CreateIdentityActivity.class);
+ container.startActivity(i);
+ } else {
+ container.setLocalAuthorId(item.getLocalAuthor().getId());
+ }
enableOrDisableContinueButton();
}
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
index effa869bc..fca12f6e4 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
@@ -149,6 +149,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener {
adapter.clear();
for(PrivateMessageHeader h : headers) adapter.add(h);
adapter.sort(AscendingHeaderComparator.INSTANCE);
+ adapter.notifyDataSetChanged();
selectFirstUnread();
}
});
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
index 950afba1c..0e8f50293 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
@@ -148,6 +148,7 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
adapter.add(new ConversationListItem(c, headerList));
adapter.sort(ConversationComparator.INSTANCE);
}
+ adapter.notifyDataSetChanged();
selectFirstUnread();
}
});
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 db08956fb..0ddfced47 100644
--- a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java
@@ -114,7 +114,7 @@ implements OnItemSelectedListener, OnClickListener {
TextView to = new TextView(this);
to.setTextSize(18);
- to.setPadding(10, 10, 10, 10);
+ to.setPadding(10, 0, 0, 10);
to.setText(R.string.to);
header.addView(to);