diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index d3580ced8b1d1e1be1feab8a2df130beebe526df..003bfac9431e47cc5b7e8937ea24514f467f8459 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 0000000000000000000000000000000000000000..fa74ee1aa7d5b2f4c95cb54f525d3e1121b68da6 --- /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 0ece0cad496a330287a7964cde875adda11992df..a612cc7b28818f0a85399a09fcd342a4429fad7c 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 b6dfdfdcabbeb29e286a0ef8a2c722391497a2a8..134c4f2fab45131d69a08bd361acc299b48c819e 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 6d9ce55b7b98533db58b886abac57b28faec7870..84ec78b6ce8e9c0ce7b53149e279a1fe7fd8dee9 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 15b15cfbeae485c8b574e4b52bdfe474aba5bc28..b835960ae9e768a9627552c37abf89fd1cc2f2ef 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 e8c3ac199e68ebef099516017aba565ee3e61239..57b280767b907f1fe916cce022584bd5c582fb22 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 083497f91f7849d551e02b62bc8b5436ba0d7f07..570198436c65b8a48a4e2079cfc64cefe0a0d660 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 34613b52c9a95144f115621896c01c6c31f6e8b3..1c44a75121fab73c67ea93c3ed75b2ccbda6e629 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 5a3fd556500875f3377d1a1755111bfb4c5ddba1..a600f954892bf56a86d81dd1141c13d2a9a626a8 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 1cc1f16e2bf879831b0cff66d93da7848be0f212..da6576e727c74dae6a6754e6cf18c2e4a68fd50b 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 746552eee1d40635310ee552667e4212ffe3db31..16db46e339bf51093e890eec96b3736358e5bd69 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 21162f2a66c7c2db57a96b3de5645226d853b147..ddef88e455e78a3f08f37b8b859d6f0e6becf659 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(); } }