From 371cdf0f90445ca34356a4be7022a7071499ef86 Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Sun, 21 Apr 2013 18:35:43 +0100
Subject: [PATCH] Show a placeholder if the list of available blogs/groups is
 empty.

---
 briar-android/res/values/strings.xml          |   7 +-
 .../sf/briar/android/ManageGroupsAdapter.java |  66 ----------
 .../briar/android/blogs/BlogListAdapter.java  |   2 +-
 .../android/blogs/ManageBlogsActivity.java    |  30 +++--
 .../android/blogs/ManageBlogsAdapter.java     | 112 +++++++++++++++++
 .../briar/android/blogs/ManageBlogsItem.java  |  18 +++
 .../android/groups/GroupListAdapter.java      |   2 +-
 .../android/groups/ManageGroupsActivity.java  |  27 +++--
 .../android/groups/ManageGroupsAdapter.java   | 113 ++++++++++++++++++
 .../android/groups/ManageGroupsItem.java      |  18 +++
 .../android/invitation/NetworkSetupView.java  |   7 ++
 11 files changed, 310 insertions(+), 92 deletions(-)
 delete mode 100644 briar-android/src/net/sf/briar/android/ManageGroupsAdapter.java
 create mode 100644 briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java
 create mode 100644 briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java
 create mode 100644 briar-android/src/net/sf/briar/android/groups/ManageGroupsAdapter.java
 create mode 100644 briar-android/src/net/sf/briar/android/groups/ManageGroupsItem.java

diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 83636618ba..b15bdf91c6 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -7,7 +7,7 @@
 	<string name="choose_nickname">Choose your nickname:</string>
 	<string name="choose_password">Choose your password:</string>
 	<string name="confirm_password">Confirm your password:</string>
-	<string name="format_min_password">Password must be at least %1$d characters long.</string>
+	<string name="format_min_password">Password must be at least %1$d characters long</string>
 	<string name="enter_password">Enter your password:</string>
 	<string name="try_again">Wrong password, try again:</string>
 	<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
@@ -32,6 +32,7 @@
 	<string name="bluetooth_disabled">Bluetooth is OFF</string>
 	<string name="bluetooth_not_discoverable">Bluetooth is NOT DISCOVERABLE</string>
 	<string name="bluetooth_enabled">Bluetooth is discoverable</string>
+	<string name="fact_to_face">For security reasons you must be face-to-face with someone to add them as a contact</string>
 	<string name="continue_button">Continue</string>
 	<string name="your_invitation_code">Your invitation code is</string>
 	<string name="enter_invitation_code">Please enter your contact\'s invitation code:</string>
@@ -69,12 +70,14 @@
 	<string name="group_visible_to_some">Share this group with chosen contacts</string>
 	<string name="new_post_title">New Post</string>
 	<string name="new_group_item">New group\u2026</string>
+	<string name="manage_subscriptions_title">Manage Subscriptions</string>
+	<string name="no_groups_available">No groups available from contacts</string>
 	<string name="blogs_title">Blogs</string>
 	<plurals name="blogs_available">
 	    <item quantity="one">%1$d blog available from contacts</item>
 	    <item quantity="other">%1$d blogs available from contacts</item>
 	</plurals>
-	<string name="manage_subscriptions_title">Manage Subscriptions</string>
+	<string name="no_blogs_available">No blogs available from contacts</string>
 	<string name="subscribed_all">Subscribed, shared with all contacts</string>
 	<string name="subscribed_some">Subscribed, shared with chosen contacts</string>
 	<string name="not_subscribed">Not subscribed</string>
diff --git a/briar-android/src/net/sf/briar/android/ManageGroupsAdapter.java b/briar-android/src/net/sf/briar/android/ManageGroupsAdapter.java
deleted file mode 100644
index cddca63333..0000000000
--- a/briar-android/src/net/sf/briar/android/ManageGroupsAdapter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package net.sf.briar.android;
-
-import static android.view.View.INVISIBLE;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-
-import java.util.ArrayList;
-
-import net.sf.briar.R;
-import net.sf.briar.api.messaging.GroupStatus;
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-public class ManageGroupsAdapter extends ArrayAdapter<GroupStatus>
-implements ListAdapter {
-
-	public ManageGroupsAdapter(Context ctx) {
-		super(ctx, android.R.layout.simple_expandable_list_item_1,
-				new ArrayList<GroupStatus>());
-	}
-
-	@Override
-	public View getView(int position, View convertView, ViewGroup parent) {
-		final GroupStatus item = getItem(position);
-		Context ctx = getContext();
-
-		LinearLayout layout = new LinearLayout(ctx);
-		layout.setOrientation(HORIZONTAL);
-
-		ImageView subscribed = new ImageView(ctx);
-		subscribed.setPadding(5, 5, 5, 5);
-		subscribed.setImageResource(R.drawable.navigation_accept);
-		if(!item.isSubscribed()) subscribed.setVisibility(INVISIBLE);
-		layout.addView(subscribed);
-
-		LinearLayout innerLayout = new LinearLayout(ctx);
-		innerLayout.setOrientation(VERTICAL);
-
-		TextView name = new TextView(ctx);
-		name.setTextSize(18);
-		name.setMaxLines(1);
-		name.setPadding(0, 10, 10, 10);
-		name.setText(item.getGroup().getName());
-		innerLayout.addView(name);
-
-		TextView status = new TextView(ctx);
-		status.setTextSize(14);
-		status.setPadding(0, 0, 10, 10);
-		if(item.isSubscribed()) {
-			if(item.isVisibleToAll()) status.setText(R.string.subscribed_all);
-			else status.setText(R.string.subscribed_some);
-		} else {
-			status.setText(R.string.not_subscribed);
-		}
-		innerLayout.addView(status);
-		layout.addView(innerLayout);
-
-		return layout;
-	}
-}
diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java b/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java
index 4721572612..470ee405c8 100644
--- a/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java
+++ b/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java
@@ -137,7 +137,7 @@ class BlogListAdapter extends BaseAdapter {
 
 	@Override
 	public boolean isEmpty() {
-		return false;
+		return list.isEmpty() && available == 0;
 	}
 
 	public void remove(BlogListItem item) {
diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java
index e464217cab..539203a68e 100644
--- a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java
+++ b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java
@@ -2,6 +2,7 @@ package net.sf.briar.android.blogs;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static net.sf.briar.android.blogs.ManageBlogsItem.NONE;
 import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
 
 import java.util.ArrayList;
@@ -15,7 +16,6 @@ import java.util.logging.Logger;
 import net.sf.briar.android.BriarFragmentActivity;
 import net.sf.briar.android.BriarService;
 import net.sf.briar.android.BriarService.BriarServiceConnection;
-import net.sf.briar.android.ManageGroupsAdapter;
 import net.sf.briar.api.android.DatabaseUiExecutor;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
@@ -44,7 +44,7 @@ implements DatabaseListener, OnItemClickListener {
 	private final BriarServiceConnection serviceConnection =
 			new BriarServiceConnection();
 
-	private ManageGroupsAdapter adapter = null;
+	private ManageBlogsAdapter adapter = null;
 	private ListView list = null;
 
 	// Fields that are accessed from background threads must be volatile
@@ -55,7 +55,7 @@ implements DatabaseListener, OnItemClickListener {
 	public void onCreate(Bundle state) {
 		super.onCreate(null);
 
-		adapter = new ManageGroupsAdapter(this);
+		adapter = new ManageBlogsAdapter(this);
 		list = new ListView(this);
 		list.setLayoutParams(MATCH_MATCH);
 		list.setAdapter(adapter);
@@ -105,7 +105,8 @@ implements DatabaseListener, OnItemClickListener {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				adapter.clear();
-				for(GroupStatus g : available) adapter.add(g);
+				for(GroupStatus g : available)
+					adapter.add(new ManageBlogsItem(g));
 				adapter.sort(ItemComparator.INSTANCE);
 				adapter.notifyDataSetChanged();
 			}
@@ -146,24 +147,29 @@ implements DatabaseListener, OnItemClickListener {
 
 	public void onItemClick(AdapterView<?> parent, View view, int position,
 			long id) {
-		GroupStatus item = adapter.getItem(position);
-		Group g = item.getGroup();
+		ManageBlogsItem item = adapter.getItem(position);
+		if(item == NONE) return;
+		GroupStatus s = item.getGroupStatus();
+		Group g = s.getGroup();
 		Intent i = new Intent(this, ConfigureBlogActivity.class);
 		i.putExtra("net.sf.briar.GROUP_ID", g.getId().getBytes());
 		i.putExtra("net.sf.briar.GROUP_NAME", g.getName());
 		i.putExtra("net.sf.briar.PUBLIC_KEY", g.getPublicKey());
-		i.putExtra("net.sf.briar.SUBSCRIBED", item.isSubscribed());
-		i.putExtra("net.sf.briar.VISIBLE_TO_ALL", item.isVisibleToAll());
+		i.putExtra("net.sf.briar.SUBSCRIBED", s.isSubscribed());
+		i.putExtra("net.sf.briar.VISIBLE_TO_ALL", s.isVisibleToAll());
 		startActivity(i);
 	}
 
-	private static class ItemComparator implements Comparator<GroupStatus> {
+	private static class ItemComparator implements Comparator<ManageBlogsItem> {
 
 		private static final ItemComparator INSTANCE = new ItemComparator();
 
-		public int compare(GroupStatus a, GroupStatus b) {
-			String aName = a.getGroup().getName();
-			String bName = b.getGroup().getName();
+		public int compare(ManageBlogsItem a, ManageBlogsItem b) {
+			if(a == b) return 0;
+			if(a == NONE) return 1;
+			if(b == NONE) return -1;
+			String aName = a.getGroupStatus().getGroup().getName();
+			String bName = b.getGroupStatus().getGroup().getName();
 			return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
 		}
 	}
diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java
new file mode 100644
index 0000000000..6afe109f17
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java
@@ -0,0 +1,112 @@
+package net.sf.briar.android.blogs;
+
+import static android.view.Gravity.CENTER;
+import static android.view.View.INVISIBLE;
+import static android.widget.LinearLayout.HORIZONTAL;
+import static android.widget.LinearLayout.VERTICAL;
+import static net.sf.briar.android.blogs.ManageBlogsItem.NONE;
+
+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.messaging.GroupStatus;
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+class ManageBlogsAdapter extends BaseAdapter {
+
+	private final Context ctx;
+	private final List<ManageBlogsItem> list = new ArrayList<ManageBlogsItem>();
+
+	ManageBlogsAdapter(Context ctx) {
+		this.ctx = ctx;
+	}
+
+	public void add(ManageBlogsItem item) {
+		list.add(item);
+	}
+
+	public void clear() {
+		list.clear();
+	}
+
+	public int getCount() {
+		return list.isEmpty() ? 1 : list.size();
+	}
+
+	public ManageBlogsItem getItem(int position) {
+		return list.isEmpty() ? NONE : list.get(position);
+	}
+
+	public long getItemId(int position) {
+		return android.R.layout.simple_expandable_list_item_1;
+	}
+
+	public View getView(int position, View convertView, ViewGroup parent) {
+		ManageBlogsItem item = getItem(position);
+
+		if(item == NONE) {
+			TextView none = new TextView(ctx);
+			none.setGravity(CENTER);
+			none.setTextSize(18);
+			none.setPadding(10, 10, 10, 10);
+			none.setText(R.string.no_blogs_available);
+			return none;
+		}
+
+		GroupStatus s = item.getGroupStatus();
+		LinearLayout layout = new LinearLayout(ctx);
+		layout.setOrientation(HORIZONTAL);
+
+		ImageView subscribed = new ImageView(ctx);
+		subscribed.setPadding(5, 5, 5, 5);
+		subscribed.setImageResource(R.drawable.navigation_accept);
+		if(!s.isSubscribed()) subscribed.setVisibility(INVISIBLE);
+		layout.addView(subscribed);
+
+		LinearLayout innerLayout = new LinearLayout(ctx);
+		innerLayout.setOrientation(VERTICAL);
+
+		TextView name = new TextView(ctx);
+		name.setTextSize(18);
+		name.setMaxLines(1);
+		name.setPadding(0, 10, 10, 10);
+		name.setText(s.getGroup().getName());
+		innerLayout.addView(name);
+
+		TextView status = new TextView(ctx);
+		status.setTextSize(14);
+		status.setPadding(0, 0, 10, 10);
+		if(s.isSubscribed()) {
+			if(s.isVisibleToAll()) status.setText(R.string.subscribed_all);
+			else status.setText(R.string.subscribed_some);
+		} else {
+			status.setText(R.string.not_subscribed);
+		}
+		innerLayout.addView(status);
+		layout.addView(innerLayout);
+
+		return layout;
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return false;
+	}
+
+	public void remove(ManageBlogsItem item) {
+		list.remove(item);
+	}
+
+	public void sort(Comparator<ManageBlogsItem> comparator) {
+		Collections.sort(list, comparator);
+	}
+}
diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java
new file mode 100644
index 0000000000..dfa61ea77d
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java
@@ -0,0 +1,18 @@
+package net.sf.briar.android.blogs;
+
+import net.sf.briar.api.messaging.GroupStatus;
+
+class ManageBlogsItem {
+
+	static final ManageBlogsItem NONE = new ManageBlogsItem(null);
+
+	private final GroupStatus status;
+
+	ManageBlogsItem(GroupStatus status) {
+		this.status = status;
+	}
+
+	GroupStatus getGroupStatus() {
+		return status;
+	}
+}
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
index e6bc316444..0c34a0e6ba 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
@@ -137,7 +137,7 @@ class GroupListAdapter extends BaseAdapter {
 
 	@Override
 	public boolean isEmpty() {
-		return false;
+		return list.isEmpty() && available == 0;
 	}
 
 	public void remove(GroupListItem item) {
diff --git a/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java b/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
index 421086dbb3..976f8b9a55 100644
--- a/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
@@ -2,6 +2,7 @@ package net.sf.briar.android.groups;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static net.sf.briar.android.groups.ManageGroupsItem.NONE;
 import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
 
 import java.util.ArrayList;
@@ -15,7 +16,6 @@ import java.util.logging.Logger;
 import net.sf.briar.android.BriarFragmentActivity;
 import net.sf.briar.android.BriarService;
 import net.sf.briar.android.BriarService.BriarServiceConnection;
-import net.sf.briar.android.ManageGroupsAdapter;
 import net.sf.briar.api.android.DatabaseUiExecutor;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
@@ -105,7 +105,8 @@ implements DatabaseListener, OnItemClickListener {
 		runOnUiThread(new Runnable() {
 			public void run() {
 				adapter.clear();
-				for(GroupStatus g : available) adapter.add(g);
+				for(GroupStatus g : available)
+					adapter.add(new ManageGroupsItem(g));
 				adapter.sort(ItemComparator.INSTANCE);
 				adapter.notifyDataSetChanged();
 			}
@@ -146,23 +147,29 @@ implements DatabaseListener, OnItemClickListener {
 
 	public void onItemClick(AdapterView<?> parent, View view, int position,
 			long id) {
-		GroupStatus item = adapter.getItem(position);
-		Group g = item.getGroup();
+		ManageGroupsItem item = adapter.getItem(position);
+		if(item == NONE) return;
+		GroupStatus s = item.getGroupStatus();
+		Group g = s.getGroup();
 		Intent i = new Intent(this, ConfigureGroupActivity.class);
 		i.putExtra("net.sf.briar.GROUP_ID", g.getId().getBytes());
 		i.putExtra("net.sf.briar.GROUP_NAME", g.getName());
-		i.putExtra("net.sf.briar.SUBSCRIBED", item.isSubscribed());
-		i.putExtra("net.sf.briar.VISIBLE_TO_ALL", item.isVisibleToAll());
+		i.putExtra("net.sf.briar.SUBSCRIBED", s.isSubscribed());
+		i.putExtra("net.sf.briar.VISIBLE_TO_ALL", s.isVisibleToAll());
 		startActivity(i);
 	}
 
-	private static class ItemComparator implements Comparator<GroupStatus> {
+	private static class ItemComparator
+	implements Comparator<ManageGroupsItem> {
 
 		private static final ItemComparator INSTANCE = new ItemComparator();
 
-		public int compare(GroupStatus a, GroupStatus b) {
-			String aName = a.getGroup().getName();
-			String bName = b.getGroup().getName();
+		public int compare(ManageGroupsItem a, ManageGroupsItem b) {
+			if(a == b) return 0;
+			if(a == NONE) return 1;
+			if(b == NONE) return -1;
+			String aName = a.getGroupStatus().getGroup().getName();
+			String bName = b.getGroupStatus().getGroup().getName();
 			return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
 		}
 	}
diff --git a/briar-android/src/net/sf/briar/android/groups/ManageGroupsAdapter.java b/briar-android/src/net/sf/briar/android/groups/ManageGroupsAdapter.java
new file mode 100644
index 0000000000..77565ef61c
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/groups/ManageGroupsAdapter.java
@@ -0,0 +1,113 @@
+package net.sf.briar.android.groups;
+
+import static android.view.Gravity.CENTER;
+import static android.view.View.INVISIBLE;
+import static android.widget.LinearLayout.HORIZONTAL;
+import static android.widget.LinearLayout.VERTICAL;
+import static net.sf.briar.android.groups.ManageGroupsItem.NONE;
+
+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.messaging.GroupStatus;
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+class ManageGroupsAdapter extends BaseAdapter {
+
+	private final Context ctx;
+	private final List<ManageGroupsItem> list =
+			new ArrayList<ManageGroupsItem>();
+
+	ManageGroupsAdapter(Context ctx) {
+		this.ctx = ctx;
+	}
+
+	public void add(ManageGroupsItem item) {
+		list.add(item);
+	}
+
+	public void clear() {
+		list.clear();
+	}
+
+	public int getCount() {
+		return list.isEmpty() ? 1 : list.size();
+	}
+
+	public ManageGroupsItem getItem(int position) {
+		return list.isEmpty() ? NONE : list.get(position);
+	}
+
+	public long getItemId(int position) {
+		return android.R.layout.simple_expandable_list_item_1;
+	}
+
+	public View getView(int position, View convertView, ViewGroup parent) {
+		ManageGroupsItem item = getItem(position);
+
+		if(item == NONE) {
+			TextView none = new TextView(ctx);
+			none.setGravity(CENTER);
+			none.setTextSize(18);
+			none.setPadding(10, 10, 10, 10);
+			none.setText(R.string.no_groups_available);
+			return none;
+		}
+
+		GroupStatus s = item.getGroupStatus();
+		LinearLayout layout = new LinearLayout(ctx);
+		layout.setOrientation(HORIZONTAL);
+
+		ImageView subscribed = new ImageView(ctx);
+		subscribed.setPadding(5, 5, 5, 5);
+		subscribed.setImageResource(R.drawable.navigation_accept);
+		if(!s.isSubscribed()) subscribed.setVisibility(INVISIBLE);
+		layout.addView(subscribed);
+
+		LinearLayout innerLayout = new LinearLayout(ctx);
+		innerLayout.setOrientation(VERTICAL);
+
+		TextView name = new TextView(ctx);
+		name.setTextSize(18);
+		name.setMaxLines(1);
+		name.setPadding(0, 10, 10, 10);
+		name.setText(s.getGroup().getName());
+		innerLayout.addView(name);
+
+		TextView status = new TextView(ctx);
+		status.setTextSize(14);
+		status.setPadding(0, 0, 10, 10);
+		if(s.isSubscribed()) {
+			if(s.isVisibleToAll()) status.setText(R.string.subscribed_all);
+			else status.setText(R.string.subscribed_some);
+		} else {
+			status.setText(R.string.not_subscribed);
+		}
+		innerLayout.addView(status);
+		layout.addView(innerLayout);
+
+		return layout;
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return false;
+	}
+
+	public void remove(ManageGroupsItem item) {
+		list.remove(item);
+	}
+
+	public void sort(Comparator<ManageGroupsItem> comparator) {
+		Collections.sort(list, comparator);
+	}
+}
diff --git a/briar-android/src/net/sf/briar/android/groups/ManageGroupsItem.java b/briar-android/src/net/sf/briar/android/groups/ManageGroupsItem.java
new file mode 100644
index 0000000000..29b19baa05
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/groups/ManageGroupsItem.java
@@ -0,0 +1,18 @@
+package net.sf.briar.android.groups;
+
+import net.sf.briar.api.messaging.GroupStatus;
+
+class ManageGroupsItem {
+
+	static final ManageGroupsItem NONE = new ManageGroupsItem(null);
+
+	private final GroupStatus status;
+
+	ManageGroupsItem(GroupStatus status) {
+		this.status = status;
+	}
+
+	GroupStatus getGroupStatus() {
+		return status;
+	}
+}
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 39698b0e14..90343a0225 100644
--- a/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java
+++ b/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java
@@ -63,6 +63,13 @@ OnClickListener {
 		bluetooth.init(this);
 		addView(bluetooth);
 
+		TextView faceToFace = new TextView(ctx);
+		faceToFace.setGravity(CENTER);
+		faceToFace.setTextSize(14);
+		faceToFace.setPadding(10, 10, 10, 10);
+		faceToFace.setText(R.string.fact_to_face);
+		addView(faceToFace);
+
 		continueButton = new Button(ctx);
 		continueButton.setLayoutParams(WRAP_WRAP);
 		continueButton.setText(R.string.continue_button);
-- 
GitLab