diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index d3580ced8..003bfac94 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -51,10 +51,14 @@
(No posts)
New Group
Choose a name for your group:
+ Share this group with all contacts
+ Share this group with chosen contacts
New Post
Blogs
New Blog
Choose a name for your blog:
+ Share this blog with all contacts
+ Share this blog with chosen contacts
New Post
New nickname\u2026
Create an Identity
diff --git a/briar-android/src/net/sf/briar/android/SelectContactsDialog.java b/briar-android/src/net/sf/briar/android/SelectContactsDialog.java
new file mode 100644
index 000000000..fa74ee1aa
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/SelectContactsDialog.java
@@ -0,0 +1,65 @@
+package net.sf.briar.android;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.sf.briar.R;
+import net.sf.briar.api.Contact;
+import net.sf.briar.api.ContactId;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+
+public class SelectContactsDialog extends DialogFragment
+implements DialogInterface.OnMultiChoiceClickListener {
+
+ private final Set selected = new HashSet();
+
+ private Listener listener = null;
+ private Contact[] contacts = null;
+
+ public void setListener(Listener listener) {
+ this.listener = listener;
+ }
+
+ public void setContacts(Collection contacts) {
+ this.contacts = contacts.toArray(this.contacts);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle state) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ String[] names = new String[contacts.length];
+ for(int i = 0; i < contacts.length; i++)
+ names[i] = contacts[i].getAuthor().getName();
+ builder.setMultiChoiceItems(names, new boolean[contacts.length], this);
+ builder.setPositiveButton(R.string.done_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ listener.contactsSelected(selected);
+ }
+ });
+ builder.setNegativeButton(R.string.cancel_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ listener.contactSelectionCancelled();
+ }
+ });
+ return builder.create();
+ }
+
+ public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+ if(isChecked) selected.add(contacts[which].getId());
+ else selected.remove(contacts[which].getId());
+ }
+
+ public interface Listener {
+
+ void contactsSelected(Collection selected);
+
+ void contactSelectionCancelled();
+ }
+}
diff --git a/briar-android/src/net/sf/briar/android/SetupActivity.java b/briar-android/src/net/sf/briar/android/SetupActivity.java
index 0ece0cad4..a612cc7b2 100644
--- a/briar-android/src/net/sf/briar/android/SetupActivity.java
+++ b/briar-android/src/net/sf/briar/android/SetupActivity.java
@@ -65,7 +65,14 @@ implements OnEditorActionListener, OnClickListener {
chooseNickname.setText(R.string.choose_nickname);
layout.addView(chooseNickname);
- nicknameEntry = new EditText(this);
+ nicknameEntry = new EditText(this) {
+ @Override
+ protected void onTextChanged(CharSequence text, int start,
+ int lengthBefore, int lengthAfter) {
+ if(createButton != null)
+ createButton.setEnabled(lengthAfter > 0);
+ }
+ };
nicknameEntry.setTextSize(18);
nicknameEntry.setMaxLines(1);
nicknameEntry.setPadding(10, 10, 10, 10);
@@ -77,6 +84,7 @@ implements OnEditorActionListener, OnClickListener {
createButton = new Button(this);
createButton.setLayoutParams(WRAP_WRAP);
createButton.setText(R.string.create_button);
+ createButton.setEnabled(false);
createButton.setOnClickListener(this);
layout.addView(createButton);
diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java b/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java
index b6dfdfdca..134c4f2fa 100644
--- a/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java
+++ b/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java
@@ -289,13 +289,11 @@ implements OnClickListener, DatabaseListener, NoBlogsDialog.Listener {
});
}
- public void createGroupButtonClicked() {
+ public void blogCreationSelected() {
startActivity(new Intent(this, CreateBlogActivity.class));
}
- public void cancelButtonClicked() {
- // That's nice dear
- }
+ public void blogCreationCancelled() {}
private static class GroupComparator implements Comparator {
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 6d9ce55b7..84ec78b6c 100644
--- a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java
+++ b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java
@@ -15,13 +15,20 @@ import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP;
import java.io.IOException;
import java.security.KeyPair;
+import java.util.Collection;
+import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.sf.briar.R;
-import net.sf.briar.android.BriarActivity;
+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.invitation.AddContactActivity;
+import net.sf.briar.android.messages.NoContactsDialog;
+import net.sf.briar.api.Contact;
+import net.sf.briar.api.ContactId;
import net.sf.briar.api.android.DatabaseUiExecutor;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.CryptoExecutor;
@@ -39,13 +46,16 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.google.inject.Inject;
-public class CreateBlogActivity extends BriarActivity
-implements OnEditorActionListener, OnClickListener {
+public class CreateBlogActivity extends BriarFragmentActivity
+implements OnEditorActionListener, OnClickListener, NoContactsDialog.Listener,
+SelectContactsDialog.Listener {
private static final Logger LOG =
Logger.getLogger(CreateBlogActivity.class.getName());
@@ -55,6 +65,8 @@ implements OnEditorActionListener, OnClickListener {
@Inject @CryptoExecutor private Executor cryptoExecutor;
private EditText nameEntry = null;
+ private RadioGroup radioGroup = null;
+ private RadioButton visibleToAll = null, visibleToSome = null;
private Button createButton = null;
private ProgressBar progress = null;
@@ -63,6 +75,7 @@ implements OnEditorActionListener, OnClickListener {
@Inject private volatile GroupFactory groupFactory;
@Inject private volatile DatabaseComponent db;
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
+ private volatile Collection selected = Collections.emptyList();
@Override
public void onCreate(Bundle state) {
@@ -72,25 +85,45 @@ implements OnEditorActionListener, OnClickListener {
layout.setOrientation(VERTICAL);
layout.setGravity(CENTER_HORIZONTAL);
- TextView chooseNickname = new TextView(this);
- chooseNickname.setGravity(CENTER);
- chooseNickname.setTextSize(18);
- chooseNickname.setPadding(10, 10, 10, 10);
- chooseNickname.setText(R.string.choose_blog_name);
- layout.addView(chooseNickname);
+ TextView chooseName = new TextView(this);
+ chooseName.setGravity(CENTER);
+ chooseName.setTextSize(18);
+ chooseName.setPadding(10, 10, 10, 10);
+ chooseName.setText(R.string.choose_blog_name);
+ layout.addView(chooseName);
- nameEntry = new EditText(this);
+ nameEntry = new EditText(this) {
+ @Override
+ protected void onTextChanged(CharSequence text, int start,
+ int lengthBefore, int lengthAfter) {
+ enableOrDisableCreateButton();
+ }
+ };
nameEntry.setTextSize(18);
nameEntry.setMaxLines(1);
nameEntry.setPadding(10, 10, 10, 10);
- int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES;
- nameEntry.setInputType(inputType);
+ nameEntry.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES);
nameEntry.setOnEditorActionListener(this);
layout.addView(nameEntry);
+ radioGroup = new RadioGroup(this);
+ radioGroup.setOrientation(VERTICAL);
+
+ visibleToAll = new RadioButton(this);
+ visibleToAll.setText(R.string.blog_visible_to_all);
+ visibleToAll.setOnClickListener(this);
+ radioGroup.addView(visibleToAll);
+
+ visibleToSome = new RadioButton(this);
+ visibleToSome.setText(R.string.blog_visible_to_some);
+ visibleToSome.setOnClickListener(this);
+ radioGroup.addView(visibleToSome);
+ layout.addView(radioGroup);
+
createButton = new Button(this);
createButton.setLayoutParams(WRAP_WRAP);
createButton.setText(R.string.create_button);
+ createButton.setEnabled(false);
createButton.setOnClickListener(this);
layout.addView(createButton);
@@ -107,6 +140,14 @@ implements OnEditorActionListener, OnClickListener {
serviceConnection, 0);
}
+ private void enableOrDisableCreateButton() {
+ if(nameEntry == null || radioGroup == null || createButton == null)
+ return; // Activity not created yet
+ boolean nameNotEmpty = nameEntry.getText().length() > 0;
+ boolean visibilitySelected = radioGroup.getCheckedRadioButtonId() != -1;
+ createButton.setEnabled(nameNotEmpty && visibilitySelected);
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
@@ -119,30 +160,82 @@ implements OnEditorActionListener, OnClickListener {
}
public void onClick(View view) {
- if(!validateName()) return;
- final String name = nameEntry.getText().toString();
- // Replace the button with a progress bar
- createButton.setVisibility(GONE);
- progress.setVisibility(VISIBLE);
- // Create the blog in a background thread
- cryptoExecutor.execute(new Runnable() {
- public void run() {
- KeyPair keyPair = crypto.generateSignatureKeyPair();
- final byte[] publicKey = keyPair.getPublic().getEncoded();
- final byte[] privateKey = keyPair.getPrivate().getEncoded();
- LocalGroup g;
- try {
- g = groupFactory.createLocalGroup(name, publicKey,
- privateKey);
- } catch(IOException e) {
- throw new RuntimeException(e);
+ if(view == visibleToAll) {
+ enableOrDisableCreateButton();
+ } else if(view == visibleToSome) {
+ loadContacts();
+ } else if(view == createButton) {
+ if(!validateName()) return;
+ final String name = nameEntry.getText().toString();
+ final boolean all = visibleToAll.isChecked();
+ final Collection visible =
+ Collections.unmodifiableCollection(selected);
+ // Replace the button with a progress bar
+ createButton.setVisibility(GONE);
+ progress.setVisibility(VISIBLE);
+ // Create the blog in a background thread
+ cryptoExecutor.execute(new Runnable() {
+ public void run() {
+ KeyPair keyPair = crypto.generateSignatureKeyPair();
+ final byte[] publicKey = keyPair.getPublic().getEncoded();
+ final byte[] privateKey = keyPair.getPrivate().getEncoded();
+ LocalGroup g;
+ try {
+ g = groupFactory.createLocalGroup(name, publicKey,
+ privateKey);
+ } catch(IOException e) {
+ throw new RuntimeException(e);
+ }
+ storeLocalGroup(g, all, visible);
+ }
+ });
+ }
+ }
+
+ private void loadContacts() {
+ dbUiExecutor.execute(new Runnable() {
+ public void run() {
+ try {
+ serviceConnection.waitForStartup();
+ long now = System.currentTimeMillis();
+ Collection contacts = db.getContacts();
+ long duration = System.currentTimeMillis() - now;
+ if(LOG.isLoggable(INFO))
+ LOG.info("Load took " + duration + " ms");
+ displayContacts(contacts);
+ } catch(DbException e) {
+ if(LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ } catch(InterruptedException e) {
+ if(LOG.isLoggable(INFO))
+ LOG.info("Interrupted while waiting for service");
+ Thread.currentThread().interrupt();
}
- storeLocalGroup(g);
}
});
}
- private void storeLocalGroup(final LocalGroup g) {
+ private void displayContacts(final Collection contacts) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if(contacts.isEmpty()) {
+ NoContactsDialog dialog = new NoContactsDialog();
+ dialog.setListener(CreateBlogActivity.this);
+ dialog.show(getSupportFragmentManager(),
+ "NoContactsDialog");
+ } else {
+ SelectContactsDialog dialog = new SelectContactsDialog();
+ dialog.setListener(CreateBlogActivity.this);
+ dialog.setContacts(contacts);
+ dialog.show(getSupportFragmentManager(),
+ "SelectContactsDialog");
+ }
+ }
+ });
+ }
+
+ private void storeLocalGroup(final LocalGroup g, final boolean all,
+ final Collection visible) {
dbUiExecutor.execute(new Runnable() {
public void run() {
try {
@@ -150,6 +243,8 @@ implements OnEditorActionListener, OnClickListener {
long now = System.currentTimeMillis();
db.addLocalGroup(g);
db.subscribe(g);
+ if(all) db.setVisibleToAll(g.getId(), true);
+ else db.setVisibility(g.getId(), visible);
long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO))
LOG.info("Storing group took " + duration + " ms");
@@ -177,4 +272,21 @@ implements OnEditorActionListener, OnClickListener {
((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
return true;
}
+
+ public void contactCreationSelected() {
+ startActivity(new Intent(this, AddContactActivity.class));
+ }
+
+ public void contactCreationCancelled() {
+ enableOrDisableCreateButton();
+ }
+
+ public void contactsSelected(Collection selected) {
+ this.selected = selected;
+ enableOrDisableCreateButton();
+ }
+
+ public void contactSelectionCancelled() {
+ enableOrDisableCreateButton();
+ }
}
diff --git a/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java b/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java
index 15b15cfbe..b835960ae 100644
--- a/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java
+++ b/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java
@@ -22,13 +22,13 @@ public class NoBlogsDialog extends DialogFragment {
builder.setPositiveButton(R.string.create_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.createGroupButtonClicked();
+ listener.blogCreationSelected();
}
});
builder.setNegativeButton(R.string.cancel_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.cancelButtonClicked();
+ listener.blogCreationCancelled();
}
});
return builder.create();
@@ -36,8 +36,8 @@ public class NoBlogsDialog extends DialogFragment {
interface Listener {
- void createGroupButtonClicked();
+ void blogCreationSelected();
- void cancelButtonClicked();
+ void blogCreationCancelled();
}
}
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 e8c3ac199..57b280767 100644
--- a/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java
@@ -14,13 +14,20 @@ import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP;
import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.sf.briar.R;
-import net.sf.briar.android.BriarActivity;
+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.invitation.AddContactActivity;
+import net.sf.briar.android.messages.NoContactsDialog;
+import net.sf.briar.api.Contact;
+import net.sf.briar.api.ContactId;
import net.sf.briar.api.android.DatabaseUiExecutor;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
@@ -36,13 +43,16 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.google.inject.Inject;
-public class CreateGroupActivity extends BriarActivity
-implements OnEditorActionListener, OnClickListener {
+public class CreateGroupActivity extends BriarFragmentActivity
+implements OnEditorActionListener, OnClickListener, NoContactsDialog.Listener,
+SelectContactsDialog.Listener {
private static final Logger LOG =
Logger.getLogger(CreateGroupActivity.class.getName());
@@ -51,6 +61,8 @@ implements OnEditorActionListener, OnClickListener {
new BriarServiceConnection();
private EditText nameEntry = null;
+ private RadioGroup radioGroup = null;
+ private RadioButton visibleToAll = null, visibleToSome = null;
private Button createButton = null;
private ProgressBar progress = null;
@@ -58,6 +70,7 @@ implements OnEditorActionListener, OnClickListener {
@Inject private volatile GroupFactory groupFactory;
@Inject private volatile DatabaseComponent db;
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
+ private volatile Collection selected = Collections.emptyList();
@Override
public void onCreate(Bundle state) {
@@ -67,22 +80,41 @@ implements OnEditorActionListener, OnClickListener {
layout.setOrientation(VERTICAL);
layout.setGravity(CENTER_HORIZONTAL);
- TextView chooseNickname = new TextView(this);
- chooseNickname.setGravity(CENTER);
- chooseNickname.setTextSize(18);
- chooseNickname.setPadding(10, 10, 10, 10);
- chooseNickname.setText(R.string.choose_group_name);
- layout.addView(chooseNickname);
+ TextView chooseName = new TextView(this);
+ chooseName.setGravity(CENTER);
+ chooseName.setTextSize(18);
+ chooseName.setPadding(10, 10, 10, 10);
+ chooseName.setText(R.string.choose_group_name);
+ layout.addView(chooseName);
- nameEntry = new EditText(this);
+ nameEntry = new EditText(this) {
+ @Override
+ protected void onTextChanged(CharSequence text, int start,
+ int lengthBefore, int lengthAfter) {
+ enableOrDisableCreateButton();
+ }
+ };
nameEntry.setTextSize(18);
nameEntry.setMaxLines(1);
nameEntry.setPadding(10, 10, 10, 10);
- int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES;
- nameEntry.setInputType(inputType);
+ nameEntry.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES);
nameEntry.setOnEditorActionListener(this);
layout.addView(nameEntry);
+ radioGroup = new RadioGroup(this);
+ radioGroup.setOrientation(VERTICAL);
+
+ visibleToAll = new RadioButton(this);
+ visibleToAll.setText(R.string.blog_visible_to_all);
+ visibleToAll.setOnClickListener(this);
+ radioGroup.addView(visibleToAll);
+
+ visibleToSome = new RadioButton(this);
+ visibleToSome.setText(R.string.blog_visible_to_some);
+ visibleToSome.setOnClickListener(this);
+ radioGroup.addView(visibleToSome);
+ layout.addView(radioGroup);
+
createButton = new Button(this);
createButton.setLayoutParams(WRAP_WRAP);
createButton.setText(R.string.create_button);
@@ -102,6 +134,14 @@ implements OnEditorActionListener, OnClickListener {
serviceConnection, 0);
}
+ private void enableOrDisableCreateButton() {
+ if(nameEntry == null || radioGroup == null || createButton == null)
+ return; // Activity not created yet
+ boolean nameNotEmpty = nameEntry.getText().length() > 0;
+ boolean visibilitySelected = radioGroup.getCheckedRadioButtonId() != -1;
+ createButton.setEnabled(nameNotEmpty && visibilitySelected);
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
@@ -114,22 +154,64 @@ implements OnEditorActionListener, OnClickListener {
}
public void onClick(View view) {
- if(!validateName()) return;
- final String name = nameEntry.getText().toString();
- // Replace the button with a progress bar
- createButton.setVisibility(GONE);
- progress.setVisibility(VISIBLE);
- // Create and store the group in a background thread
+ if(view == visibleToAll) {
+ enableOrDisableCreateButton();
+ } else if(view == visibleToSome) {
+ loadContacts();
+ } else if(view == createButton) {
+ if(!validateName()) return;
+ final String name = nameEntry.getText().toString();
+ final boolean all = visibleToAll.isChecked();
+ final Collection visible =
+ Collections.unmodifiableCollection(selected);
+ // Replace the button with a progress bar
+ createButton.setVisibility(GONE);
+ progress.setVisibility(VISIBLE);
+ // Create and store the group in a background thread
+ dbUiExecutor.execute(new Runnable() {
+ public void run() {
+ try {
+ serviceConnection.waitForStartup();
+ Group g = groupFactory.createGroup(name);
+ long now = System.currentTimeMillis();
+ db.subscribe(g);
+ if(all) db.setVisibleToAll(g.getId(), true);
+ else db.setVisibility(g.getId(), visible);
+ long duration = System.currentTimeMillis() - now;
+ if(LOG.isLoggable(INFO))
+ LOG.info("Storing group took " + duration + " ms");
+ } catch(DbException e) {
+ if(LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ } catch(InterruptedException e) {
+ if(LOG.isLoggable(INFO))
+ LOG.info("Interrupted while waiting for service");
+ Thread.currentThread().interrupt();
+ } catch(IOException e) {
+ throw new RuntimeException(e);
+ }
+ runOnUiThread(new Runnable() {
+ public void run() {
+ finish();
+ }
+ });
+ }
+ });
+ }
+ }
+
+
+ private void loadContacts() {
dbUiExecutor.execute(new Runnable() {
public void run() {
try {
serviceConnection.waitForStartup();
- Group g = groupFactory.createGroup(name);
long now = System.currentTimeMillis();
- db.subscribe(g);
+ Collection contacts = db.getContacts();
long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO))
- LOG.info("Storing group took " + duration + " ms");
+ LOG.info("Load took " + duration + " ms");
+ displayContacts(contacts);
} catch(DbException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -137,14 +219,26 @@ implements OnEditorActionListener, OnClickListener {
if(LOG.isLoggable(INFO))
LOG.info("Interrupted while waiting for service");
Thread.currentThread().interrupt();
- } catch(IOException e) {
- throw new RuntimeException(e);
}
- runOnUiThread(new Runnable() {
- public void run() {
- finish();
- }
- });
+ }
+ });
+ }
+
+ private void displayContacts(final Collection contacts) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if(contacts.isEmpty()) {
+ NoContactsDialog dialog = new NoContactsDialog();
+ dialog.setListener(CreateGroupActivity.this);
+ dialog.show(getSupportFragmentManager(),
+ "NoContactsDialog");
+ } else {
+ SelectContactsDialog dialog = new SelectContactsDialog();
+ dialog.setListener(CreateGroupActivity.this);
+ dialog.setContacts(contacts);
+ dialog.show(getSupportFragmentManager(),
+ "SelectContactsDialog");
+ }
}
});
}
@@ -156,4 +250,21 @@ implements OnEditorActionListener, OnClickListener {
((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
return true;
}
+
+ public void contactCreationSelected() {
+ startActivity(new Intent(this, AddContactActivity.class));
+ }
+
+ public void contactCreationCancelled() {
+ enableOrDisableCreateButton();
+ }
+
+ public void contactsSelected(Collection selected) {
+ this.selected = selected;
+ enableOrDisableCreateButton();
+ }
+
+ public void contactSelectionCancelled() {
+ enableOrDisableCreateButton();
+ }
}
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 083497f91..570198436 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
@@ -276,13 +276,11 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
});
}
- public void createButtonClicked() {
+ public void groupCreationSelected() {
startActivity(new Intent(this, CreateGroupActivity.class));
}
- public void cancelButtonClicked() {
- // That's nice dear
- }
+ public void groupCreationCancelled() {}
private static class GroupComparator implements Comparator {
diff --git a/briar-android/src/net/sf/briar/android/groups/NoGroupsDialog.java b/briar-android/src/net/sf/briar/android/groups/NoGroupsDialog.java
index 34613b52c..1c44a7512 100644
--- a/briar-android/src/net/sf/briar/android/groups/NoGroupsDialog.java
+++ b/briar-android/src/net/sf/briar/android/groups/NoGroupsDialog.java
@@ -22,13 +22,13 @@ public class NoGroupsDialog extends DialogFragment {
builder.setPositiveButton(R.string.create_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.createButtonClicked();
+ listener.groupCreationSelected();
}
});
builder.setNegativeButton(R.string.cancel_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.cancelButtonClicked();
+ listener.groupCreationCancelled();
}
});
return builder.create();
@@ -36,8 +36,8 @@ public class NoGroupsDialog extends DialogFragment {
interface Listener {
- void createButtonClicked();
+ void groupCreationSelected();
- void cancelButtonClicked();
+ void groupCreationCancelled();
}
}
diff --git a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java
index 5a3fd5565..a600f9548 100644
--- a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java
+++ b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java
@@ -79,7 +79,14 @@ implements OnEditorActionListener, OnClickListener {
chooseNickname.setText(R.string.choose_nickname);
layout.addView(chooseNickname);
- nicknameEntry = new EditText(this);
+ nicknameEntry = new EditText(this) {
+ @Override
+ protected void onTextChanged(CharSequence text, int start,
+ int lengthBefore, int lengthAfter) {
+ if(createButton != null)
+ createButton.setEnabled(lengthAfter > 0);
+ }
+ };
nicknameEntry.setTextSize(18);
nicknameEntry.setMaxLines(1);
nicknameEntry.setPadding(10, 10, 10, 10);
@@ -91,6 +98,7 @@ implements OnEditorActionListener, OnClickListener {
createButton = new Button(this);
createButton.setLayoutParams(WRAP_WRAP);
createButton.setText(R.string.create_button);
+ createButton.setEnabled(false);
createButton.setOnClickListener(this);
layout.addView(createButton);
diff --git a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java
index 1cc1f16e2..da6576e72 100644
--- a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java
+++ b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java
@@ -23,6 +23,7 @@ implements OnEditorActionListener, OnClickListener {
private CodeEntryListener listener = null;
private EditText codeEntry = null;
+ private Button continueButton = null;
public CodeEntryWidget(Context ctx) {
super(ctx);
@@ -45,17 +46,12 @@ implements OnEditorActionListener, OnClickListener {
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
- final Button continueButton = new Button(ctx);
- continueButton.setLayoutParams(WRAP_WRAP);
- continueButton.setText(R.string.continue_button);
- continueButton.setEnabled(false);
- continueButton.setOnClickListener(this);
-
codeEntry = new EditText(ctx) {
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
- continueButton.setEnabled(text.length() == 6);
+ if(continueButton != null)
+ continueButton.setEnabled(lengthAfter == 6);
}
};
codeEntry.setTextSize(26);
@@ -66,6 +62,12 @@ implements OnEditorActionListener, OnClickListener {
codeEntry.setMaxLines(1);
codeEntry.setInputType(TYPE_CLASS_NUMBER);
innerLayout.addView(codeEntry);
+
+ continueButton = new Button(ctx);
+ continueButton.setLayoutParams(WRAP_WRAP);
+ continueButton.setText(R.string.continue_button);
+ continueButton.setEnabled(false);
+ continueButton.setOnClickListener(this);
innerLayout.addView(continueButton);
addView(innerLayout);
}
@@ -89,8 +91,8 @@ implements OnEditorActionListener, OnClickListener {
}
// Hide the soft keyboard
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
- ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
- listener.codeEntered(remoteCode);
+ ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
+ listener.codeEntered(remoteCode);
return true;
}
}
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 746552eee..16db46e33 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
@@ -238,13 +238,11 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
});
}
- public void addContactButtonClicked() {
+ public void contactCreationSelected() {
startActivity(new Intent(this, AddContactActivity.class));
}
- public void cancelButtonClicked() {
- // That's nice dear
- }
+ public void contactCreationCancelled() {}
private static class ConversationComparator
implements Comparator {
diff --git a/briar-android/src/net/sf/briar/android/messages/NoContactsDialog.java b/briar-android/src/net/sf/briar/android/messages/NoContactsDialog.java
index 21162f2a6..ddef88e45 100644
--- a/briar-android/src/net/sf/briar/android/messages/NoContactsDialog.java
+++ b/briar-android/src/net/sf/briar/android/messages/NoContactsDialog.java
@@ -11,7 +11,7 @@ public class NoContactsDialog extends DialogFragment {
private Listener listener = null;
- void setListener(Listener listener) {
+ public void setListener(Listener listener) {
this.listener = listener;
}
@@ -22,22 +22,22 @@ public class NoContactsDialog extends DialogFragment {
builder.setPositiveButton(R.string.add_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.addContactButtonClicked();
+ listener.contactCreationSelected();
}
});
builder.setNegativeButton(R.string.cancel_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- listener.cancelButtonClicked();
+ listener.contactCreationCancelled();
}
});
return builder.create();
}
- interface Listener {
+ public interface Listener {
- void addContactButtonClicked();
+ void contactCreationSelected();
- void cancelButtonClicked();
+ void contactCreationCancelled();
}
}