From 03af1d359dbe37eadef5e3ef433f6a0dcc4c2ee3 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Sat, 13 Apr 2013 23:08:51 +0100 Subject: [PATCH] Choose the visibility of blogs and groups when creating them. --- briar-android/res/values/strings.xml | 4 + .../briar/android/SelectContactsDialog.java | 65 +++++++ .../net/sf/briar/android/SetupActivity.java | 10 +- .../briar/android/blogs/BlogListActivity.java | 6 +- .../android/blogs/CreateBlogActivity.java | 170 +++++++++++++++--- .../sf/briar/android/blogs/NoBlogsDialog.java | 8 +- .../android/groups/CreateGroupActivity.java | 167 ++++++++++++++--- .../android/groups/GroupListActivity.java | 6 +- .../briar/android/groups/NoGroupsDialog.java | 8 +- .../identity/CreateIdentityActivity.java | 10 +- .../android/invitation/CodeEntryWidget.java | 20 ++- .../messages/ConversationListActivity.java | 6 +- .../android/messages/NoContactsDialog.java | 12 +- 13 files changed, 398 insertions(+), 94 deletions(-) create mode 100644 briar-android/src/net/sf/briar/android/SelectContactsDialog.java diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index d3580ced8b..003bfac943 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -51,10 +51,14 @@ <string name="no_posts">(No posts)</string> <string name="create_group_title">New Group</string> <string name="choose_group_name">Choose a name for your group:</string> + <string name="group_visible_to_all">Share this group with all contacts</string> + <string name="group_visible_to_some">Share this group with chosen contacts</string> <string name="compose_group_title">New Post</string> <string name="blogs_title">Blogs</string> <string name="create_blog_title">New Blog</string> <string name="choose_blog_name">Choose a name for your blog:</string> + <string name="blog_visible_to_all">Share this blog with all contacts</string> + <string name="blog_visible_to_some">Share this blog with chosen contacts</string> <string name="compose_blog_title">New Post</string> <string name="create_nickname_item">New nickname\u2026</string> <string name="create_identity_title">Create an Identity</string> 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 0000000000..fa74ee1aa7 --- /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<ContactId> selected = new HashSet<ContactId>(); + + private Listener listener = null; + private Contact[] contacts = null; + + public void setListener(Listener listener) { + this.listener = listener; + } + + public void setContacts(Collection<Contact> 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<ContactId> 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 0ece0cad49..a612cc7b28 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 b6dfdfdcab..134c4f2fab 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<BlogListItem> { 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 6d9ce55b7b..84ec78b6ce 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<ContactId> 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() { + 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<ContactId> 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() { - 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); + serviceConnection.waitForStartup(); + long now = System.currentTimeMillis(); + Collection<Contact> 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(); + } + } + }); + } + + private void displayContacts(final Collection<Contact> 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"); } - storeLocalGroup(g); } }); } - private void storeLocalGroup(final LocalGroup g) { + private void storeLocalGroup(final LocalGroup g, final boolean all, + final Collection<ContactId> 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<ContactId> 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 15b15cfbea..b835960ae9 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 e8c3ac199e..57b280767b 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<ContactId> 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<ContactId> 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<Contact> 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<Contact> 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<ContactId> 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 083497f91f..570198436c 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<GroupListItem> { 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 34613b52c9..1c44a75121 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 5a3fd55650..a600f95489 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 1cc1f16e2b..da6576e727 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 746552eee1..16db46e339 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<ConversationListItem> { 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 21162f2a66..ddef88e455 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(); } } -- GitLab