diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 83636618b..b15bdf91c 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -7,7 +7,7 @@
Choose your nickname:
Choose your password:
Confirm your password:
- Password must be at least %1$d characters long.
+ Password must be at least %1$d characters long
Enter your password:
Wrong password, try again:
This software has expired.\nPlease install a newer version.
@@ -32,6 +32,7 @@
Bluetooth is OFF
Bluetooth is NOT DISCOVERABLE
Bluetooth is discoverable
+ For security reasons you must be face-to-face with someone to add them as a contact
Continue
Your invitation code is
Please enter your contact\'s invitation code:
@@ -69,12 +70,14 @@
Share this group with chosen contacts
New Post
New group\u2026
+ Manage Subscriptions
+ No groups available from contacts
Blogs
- %1$d blog available from contacts
- %1$d blogs available from contacts
- Manage Subscriptions
+ No blogs available from contacts
Subscribed, shared with all contacts
Subscribed, shared with chosen contacts
Not subscribed
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 cddca6333..000000000
--- 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
-implements ListAdapter {
-
- public ManageGroupsAdapter(Context ctx) {
- super(ctx, android.R.layout.simple_expandable_list_item_1,
- new ArrayList());
- }
-
- @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 472157261..470ee405c 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 e464217ca..539203a68 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 {
+ private static class ItemComparator implements Comparator {
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 000000000..6afe109f1
--- /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 list = new ArrayList();
+
+ 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 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 000000000..dfa61ea77
--- /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 e6bc31644..0c34a0e6b 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 421086dbb..976f8b9a5 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 {
+ private static class ItemComparator
+ implements Comparator {
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 000000000..77565ef61
--- /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 list =
+ new ArrayList();
+
+ 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 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 000000000..29b19baa0
--- /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 39698b0e1..90343a022 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);