Added multiple select to Choose Contact Activity

When passing the Choose Contact Activity a boolean called "multiple"
set to true, it now allows the user to select multiple contacts. Long
pressing a contact enters multiple selection mode and the selection is
confirmed using a button in the CAB. The Activity returns whether or not
multiple contacts were selected using the same boolean. If multiple
contacts were selected, an array of JID strings called "contacts" is
returned. The Choose Contact Activity now also honors "filter_contacts",
an array of strings containing JIDs that should not be displayed in
the picker.

The invite to conference dialog now uses this feature to enable inviting
multiple contacts at once. Additionally, Invite Contact uses
"filter_contacts" to only display contacts that are not yet
participating in the conversation
This commit is contained in:
Andreas Straub 2015-03-17 15:00:50 +01:00
parent 4aab45533a
commit f76baa5658
4 changed files with 135 additions and 7 deletions

View File

@ -3,20 +3,100 @@ package eu.siacs.conversations.ui;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ListView;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.ListItem;
public class ChooseContactActivity extends AbstractSearchableListItemActivity { public class ChooseContactActivity extends AbstractSearchableListItemActivity {
private Set<Contact> selected;
private Set<String> filterContacts;
@Override @Override
public void onCreate(final Bundle savedInstanceState) { public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
filterContacts = new HashSet<>();
String[] contacts = getIntent().getStringArrayExtra("filter_contacts");
if (contacts != null) {
Collections.addAll(filterContacts, contacts);
}
if (getIntent().getBooleanExtra("multiple", false)) {
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(),
InputMethodManager.HIDE_IMPLICIT_ONLY);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.select_multiple, menu);
selected = new HashSet<Contact>();
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch(item.getItemId()) {
case R.id.selection_submit:
final Intent request = getIntent();
final Intent data = new Intent();
data.putExtra("conversation",
request.getStringExtra("conversation"));
String[] selection = getSelectedContactJids();
data.putExtra("contacts", selection);
data.putExtra("multiple", true);
setResult(RESULT_OK, data);
finish();
return true;
}
return false;
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
Contact item = (Contact) getListItems().get(position);
if (checked) {
selected.add(item);
} else {
selected.remove(item);
}
int numSelected = selected.size();
MenuItem selectButton = mode.getMenu().findItem(R.id.selection_submit);
String buttonText = getResources().getQuantityString(R.plurals.select_contact,
numSelected, numSelected);
selectButton.setTitle(buttonText);
}
});
}
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override @Override
@ -36,6 +116,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
data.putExtra("account", account); data.putExtra("account", account);
data.putExtra("conversation", data.putExtra("conversation",
request.getStringExtra("conversation")); request.getStringExtra("conversation"));
data.putExtra("multiple", false);
setResult(RESULT_OK, data); setResult(RESULT_OK, data);
finish(); finish();
} }
@ -48,7 +129,9 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
for (final Account account : xmppConnectionService.getAccounts()) { for (final Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) { if (account.getStatus() != Account.State.DISABLED) {
for (final Contact contact : account.getRoster().getContacts()) { for (final Contact contact : account.getRoster().getContacts()) {
if (contact.showInRoster() && contact.match(needle)) { if (contact.showInRoster() &&
!filterContacts.contains(contact.getJid().toBareJid().toString())
&& contact.match(needle)) {
getListItems().add(contact); getListItems().add(contact);
} }
} }
@ -57,4 +140,13 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
Collections.sort(getListItems()); Collections.sort(getListItems());
getListItemAdapter().notifyDataSetChanged(); getListItemAdapter().notifyDataSetChanged();
} }
private String[] getSelectedContactJids() {
List<String> result = new ArrayList<>();
for (Contact contact : selected) {
result.add(contact.getJid().toString());
}
return result.toArray(new String[result.size()]);
}
} }

View File

@ -69,6 +69,7 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
@ -409,7 +410,20 @@ public abstract class XmppActivity extends Activity {
protected void inviteToConversation(Conversation conversation) { protected void inviteToConversation(Conversation conversation) {
Intent intent = new Intent(getApplicationContext(), Intent intent = new Intent(getApplicationContext(),
ChooseContactActivity.class); ChooseContactActivity.class);
List<String> contacts = new ArrayList<>();
if (conversation.getMode() == Conversation.MODE_MULTI) {
for (MucOptions.User user : conversation.getMucOptions().getUsers()) {
Jid jid = user.getJid();
if (jid != null) {
contacts.add(jid.toBareJid().toString());
}
}
} else {
contacts.add(conversation.getJid().toBareJid().toString());
}
intent.putExtra("filter_contacts", contacts.toArray(new String[contacts.size()]));
intent.putExtra("conversation", conversation.getUuid()); intent.putExtra("conversation", conversation.getUuid());
intent.putExtra("multiple", true);
startActivityForResult(intent, REQUEST_INVITE_TO_CONVERSATION); startActivityForResult(intent, REQUEST_INVITE_TO_CONVERSATION);
} }
@ -652,16 +666,25 @@ public abstract class XmppActivity extends Activity {
if (requestCode == REQUEST_INVITE_TO_CONVERSATION if (requestCode == REQUEST_INVITE_TO_CONVERSATION
&& resultCode == RESULT_OK) { && resultCode == RESULT_OK) {
try { try {
Jid jid = Jid.fromString(data.getStringExtra("contact"));
String conversationUuid = data.getStringExtra("conversation"); String conversationUuid = data.getStringExtra("conversation");
Conversation conversation = xmppConnectionService Conversation conversation = xmppConnectionService
.findConversationByUuid(conversationUuid); .findConversationByUuid(conversationUuid);
if (conversation.getMode() == Conversation.MODE_MULTI) {
xmppConnectionService.invite(conversation, jid);
} else {
List<Jid> jids = new ArrayList<Jid>(); List<Jid> jids = new ArrayList<Jid>();
if (data.getBooleanExtra("multiple", false)) {
String[] toAdd = data.getStringArrayExtra("contacts");
for (String item : toAdd) {
jids.add(Jid.fromString(item));
}
} else {
jids.add(Jid.fromString(data.getStringExtra("contact")));
}
if (conversation.getMode() == Conversation.MODE_MULTI) {
for (Jid jid : jids) {
xmppConnectionService.invite(conversation, jid);
}
} else {
jids.add(conversation.getJid().toBareJid()); jids.add(conversation.getJid().toBareJid());
jids.add(jid);
xmppConnectionService.createAdhocConference(conversation.getAccount(), jids, adhocCallback); xmppConnectionService.createAdhocConference(conversation.getAccount(), jids, adhocCallback);
} }
} catch (final InvalidJidException ignored) { } catch (final InvalidJidException ignored) {

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/selection_submit"
android:title="@string/invite_contact"
android:showAsAction="always" />
</menu>

View File

@ -454,4 +454,8 @@
<string name="no_application_found_to_display_location">No application found to display location</string> <string name="no_application_found_to_display_location">No application found to display location</string>
<string name="location">Location</string> <string name="location">Location</string>
<string name="received_location">Received location</string> <string name="received_location">Received location</string>
<plurals name="select_contact">
<item quantity="one">Select %d contact</item>
<item quantity="other">Select %d contacts</item>
</plurals>
</resources> </resources>