From acb506b6333af0bcc8ae8d202c810c19899a90cb Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Thu, 11 Apr 2013 22:44:19 +0100
Subject: [PATCH] Added anonymous and new identity items to local author
 spinner.

---
 briar-android/res/values/strings.xml          |  1 +
 .../briar/android/AuthorNameComparator.java   | 16 -----
 .../net/sf/briar/android/LocalAuthorItem.java | 19 +++++
 .../android/LocalAuthorItemComparator.java    | 21 ++++++
 .../android/LocalAuthorSpinnerAdapter.java    | 71 +++++++++++++++----
 .../android/contact/ContactListActivity.java  |  1 +
 .../briar/android/groups/GroupActivity.java   |  1 +
 .../android/groups/GroupListActivity.java     |  1 +
 .../groups/WriteGroupMessageActivity.java     | 26 +++++--
 .../invitation/AddContactActivity.java        |  9 ++-
 .../android/invitation/NetworkSetupView.java  | 19 +++--
 .../messages/ConversationActivity.java        |  1 +
 .../messages/ConversationListActivity.java    |  1 +
 .../messages/WritePrivateMessageActivity.java |  2 +-
 14 files changed, 147 insertions(+), 42 deletions(-)
 delete mode 100644 briar-android/src/net/sf/briar/android/AuthorNameComparator.java
 create mode 100644 briar-android/src/net/sf/briar/android/LocalAuthorItem.java
 create mode 100644 briar-android/src/net/sf/briar/android/LocalAuthorItemComparator.java

diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index f7362082dc..9512c8e2d6 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -9,6 +9,7 @@
 	<string name="blogs_button">Blogs</string>
 	<string name="synchronize_button">Synchronize</string>
 	<string name="quit_button">Quit</string>
+	<string name="new_identity_item">New identity\u2026</string>
 	<string name="contact_list_title">Contacts</string>
 	<string name="contact_connected">Connected</string>
 	<string name="format_contact_last_connected">Last connected &lt;br /&gt; %1$s</string>
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 acde1829d8..0000000000
--- 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<Author> {
-
-	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 0000000000..0e2d63c095
--- /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 0000000000..c9ce0a1b0e
--- /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<LocalAuthorItem> {
+
+	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 668c5a4276..b112a40564 100644
--- a/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java
+++ b/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java
@@ -1,40 +1,87 @@
 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<LocalAuthor>
+public class LocalAuthorSpinnerAdapter extends BaseAdapter
 implements SpinnerAdapter {
 
-	public LocalAuthorSpinnerAdapter(Context ctx) {
-		super(ctx, android.R.layout.simple_spinner_item,
-				new ArrayList<LocalAuthor>());
+	private final Context ctx;
+	private final boolean includeAnonymous;
+	private final List<LocalAuthorItem> list = new ArrayList<LocalAuthorItem>();
+
+	public LocalAuthorSpinnerAdapter(Context ctx, boolean includeAnonymous) {
+		this.ctx = ctx;
+		this.includeAnonymous = includeAnonymous;
+	}
+
+	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
+	public View getDropDownView(int position, View convertView,
+			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(getContext());
+		TextView name = new TextView(ctx);
 		name.setTextSize(18);
 		name.setMaxLines(1);
-		Resources res = getContext().getResources();
+		Resources res = ctx.getResources();
 		int pad = res.getInteger(R.integer.spinner_padding);
 		name.setPadding(pad, pad, pad, pad);
-		name.setText(getItem(position).getName());
+		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 View getDropDownView(int position, View convertView,
-			ViewGroup parent) {
-		return getView(position, convertView, parent);
+	public boolean isEmpty() {
+		return getCount() == 0;
+	}
+
+	public void sort(Comparator<LocalAuthorItem> 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 b205c5a200..b5f83046a1 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 893442a6a0..289c85c592 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 6759acba88..45d08d452f 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 0f1f6648d3..4f7f2ff085 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 07cd6e9dae..e07efb08f7 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 2a150f0a03..ddd2ac6d6d 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 effa869bc2..fca12f6e42 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 950afba1c8..0e8f50293f 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 db08956fb9..0ddfced474 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);
 
-- 
GitLab