muc creation

This commit is contained in:
Daniel Gultsch 2014-03-15 04:59:18 +01:00
parent f3b6c99693
commit afe1244709
14 changed files with 273 additions and 51 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

View file

@ -49,7 +49,8 @@
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/contacts_header"
tools:listitem="@layout/contact" >
tools:listitem="@layout/contact"
android:choiceMode="multipleChoice">
</ListView>
</RelativeLayout>

View file

@ -3,7 +3,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:paddingBottom="8dp">
android:paddingBottom="8dp"
android:background="?android:attr/activatedBackgroundIndicator">
<ImageView
android:id="@+id/contact_photo"

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_contact_details"
android:showAsAction="ifRoom"
android:icon="@drawable/ic_action_person"
android:title="@string/action_contact_details" />
<item
android:id="@+id/action_start_conversation"
android:showAsAction="ifRoom"
android:icon="@drawable/ic_action_chat"
android:title="@string/start_conversation" />
</menu>

View file

@ -29,4 +29,5 @@
<string name="ask_again"><u>Click to ask again</u></string>
<string name="show_otr_key">OTR fingerprint</string>
<string name="no_otr_fingerprint">No OTR Fingerprint generated. Just go ahead an start an encrypted conversation</string>
<string name="start_conversation">Start Conversation</string>
</resources>

View file

@ -148,8 +148,20 @@ public class XmppConnectionService extends Service {
}
} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
message = MessageParser.parseError(packet, account, service);
} else {
// Log.d(LOGTAG, "unparsed message " + packet.toString());
} else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
if (packet.hasChild("x")) {
Element x = packet.findChild("x");
if (x.hasChild("invite")) {
findOrCreateConversation(account, packet.getFrom(), true);
if (convChangedListener != null) {
convChangedListener.onConversationListChanged();
}
Log.d(LOGTAG,"invitation received to "+packet.getFrom());
}
} else {
Log.d(LOGTAG, "unparsed message " + packet.toString());
}
}
if ((message == null)||(message.getBody() == null)) {
return;
@ -223,7 +235,7 @@ public class XmppConnectionService extends Service {
&& (packet.findChild("x").getAttribute("xmlns")
.startsWith("http://jabber.org/protocol/muc"))) {
Conversation muc = findMuc(packet.getAttribute("from").split(
"/")[0]);
"/")[0],account);
if (muc != null) {
int error = muc.getMucOptions().getError();
muc.getMucOptions().processPacket(packet);
@ -336,9 +348,9 @@ public class XmppConnectionService extends Service {
}
protected Conversation findMuc(String name) {
protected Conversation findMuc(String name, Account account) {
for (Conversation conversation : this.conversations) {
if (conversation.getContactJid().split("/")[0].equals(name)) {
if (conversation.getContactJid().split("/")[0].equals(name)&&(conversation.getAccount() == account)) {
return conversation;
}
}
@ -1246,4 +1258,21 @@ public class XmppConnectionService extends Service {
account.getXmppConnection().sendMessagePacket(packet);
}
}
public void inviteToConference(Conversation conversation,
List<Contact> contacts) {
for(Contact contact : contacts) {
MessagePacket packet = new MessagePacket();
packet.setTo(conversation.getContactJid().split("/")[0]);
packet.setFrom(conversation.getAccount().getFullJid());
Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
Element invite = new Element("invite");
invite.setAttribute("to", contact.getJid());
x.addChild(invite);
packet.addChild(x);
conversation.getAccount().getXmppConnection().sendMessagePacket(packet);
}
}
}

View file

@ -207,12 +207,14 @@ public class ConversationFragment extends Fragment {
viewHolder.imageView = (ImageView) view
.findViewById(R.id.message_photo);
viewHolder.imageView.setImageBitmap(selfBitmap);
viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator);
break;
case RECIEVED:
view = (View) inflater.inflate(
R.layout.message_recieved, null);
viewHolder.imageView = (ImageView) view
.findViewById(R.id.message_photo);
viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator);
if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
viewHolder.imageView.setImageBitmap(mBitmapCache
@ -239,7 +241,6 @@ public class ConversationFragment extends Fragment {
.findViewById(R.id.message_body);
viewHolder.time = (TextView) view
.findViewById(R.id.message_time);
viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
@ -279,7 +280,9 @@ public class ConversationFragment extends Fragment {
viewHolder.messageBody.setTextColor(0xff000000);
viewHolder.messageBody.setTypeface(null,
Typeface.NORMAL);
viewHolder.indicator.setVisibility(View.GONE);
if (item.getStatus() != Message.STATUS_ERROR) {
viewHolder.indicator.setVisibility(View.GONE);
}
}
} else {
viewHolder.indicator.setVisibility(View.GONE);

View file

@ -40,11 +40,9 @@ public class MucDetailsActivity extends XmppActivity {
@Override
public void onClick(View arg0) {
Log.d("gultsch","on click change muc");
MucOptions options = conversation.getMucOptions();
String nick = mYourNick.getText().toString();
if (!options.getNick().equals(nick)) {
Log.d("gultsch","call to change muc");
xmppConnectionService.renameInMuc(conversation, nick);
finish();
}

View file

@ -1,7 +1,9 @@
package eu.siacs.conversations.ui;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -16,11 +18,16 @@ import eu.siacs.conversations.utils.Validator;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
@ -49,6 +56,110 @@ public class NewConversationActivity extends XmppActivity {
protected String searchString = "";
private TextView contactsHeader;
private List<Account> accounts;
private List<Contact> selectedContacts = new ArrayList<Contact>();
private boolean isActionMode = false;
private ActionMode actionMode = null;
private AbsListView.MultiChoiceModeListener actionModeCallback = new AbsListView.MultiChoiceModeListener() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
menu.clear();
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.newconversation_context, menu);
SparseBooleanArray checkedItems = contactsView.getCheckedItemPositions();
selectedContacts.clear();
for(int i = 0; i < aggregatedContacts.size(); ++i) {
if (checkedItems.get(i, false)) {
selectedContacts.add(aggregatedContacts.get(i));
}
}
if (selectedContacts.size() == 0) {
menu.findItem(R.id.action_start_conversation).setVisible(false);
menu.findItem(R.id.action_contact_details).setVisible(false);
} else if (selectedContacts.size() == 1) {
menu.findItem(R.id.action_start_conversation).setVisible(true);
menu.findItem(R.id.action_contact_details).setVisible(true);
} else {
menu.findItem(R.id.action_start_conversation).setVisible(true);
menu.findItem(R.id.action_contact_details).setVisible(false);
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_start_conversation:
if (selectedContacts.size() == 1) {
startConversation(selectedContacts.get(0));
} else {
startConference();
}
break;
case R.id.action_contact_details:
Intent intent = new Intent(getApplicationContext(),ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
intent.putExtra("uuid", selectedContacts.get(0).getUuid());
startActivity(intent);
break;
default:
break;
}
// TODO Auto-generated method stub
return false;
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
}
};
private void startConference() {
if (accounts.size()>1) {
getAccountChooser(new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startConference(accounts.get(which), selectedContacts);
}
}).show();
} else {
startConference(accounts.get(0), selectedContacts);
}
}
private void startConference(Account account, List<Contact> contacts) {
SecureRandom random = new SecureRandom();
String mucName = new BigInteger(100,random).toString(32);
String serverName = account.getXmppConnection().getMucServer();
String jid = mucName+"@"+serverName;
Conversation conversation = xmppConnectionService.findOrCreateConversation(account, jid , true);
StringBuilder subject = new StringBuilder();
for(int i = 0; i < selectedContacts.size(); ++i) {
if (i+1!=selectedContacts.size()) {
subject.append(selectedContacts.get(i).getDisplayName()+", ");
} else {
subject.append(selectedContacts.get(i).getDisplayName());
}
}
xmppConnectionService.sendConversationSubject(conversation, subject.toString());
xmppConnectionService.inviteToConference(conversation, contacts);
switchToConversation(conversation, null);
}
protected void updateAggregatedContacts() {
@ -86,6 +197,20 @@ public class NewConversationActivity extends XmppActivity {
contactsAdapter.notifyDataSetChanged();
contactsView.setScrollX(0);
}
private OnItemLongClickListener onLongClickListener = new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View view,
int position, long arg3) {
if (!isActionMode) {
contactsView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
contactsView.setItemChecked(position,true);
actionMode = contactsView.startActionMode(actionModeCallback);
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -143,43 +268,40 @@ public class NewConversationActivity extends XmppActivity {
}
};
contactsView.setAdapter(contactsAdapter);
final Activity activity = this;
contactsView.setMultiChoiceModeListener(actionModeCallback);
contactsView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, final View view,
int pos, long arg3) {
final Contact clickedContact = aggregatedContacts.get(pos);
if ((clickedContact.getAccount()==null)&&(accounts.size()>1)) {
getAccountChooser(new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
clickedContact.setAccount(accounts.get(which));
showIsMucDialogIfNeeded(clickedContact);
}
}).show();
if (!isActionMode) {
Contact clickedContact = aggregatedContacts.get(pos);
startConversation(clickedContact);
} else {
if (clickedContact.getAccount()==null) {
clickedContact.setAccount(accounts.get(0));
}
showIsMucDialogIfNeeded(clickedContact);
actionMode.invalidate();
}
}
});
contactsView.setOnItemLongClickListener(new OnItemLongClickListener() {
contactsView.setOnItemLongClickListener(this.onLongClickListener);
}
public void startConversation(final Contact contact) {
if ((contact.getAccount()==null)&&(accounts.size()>1)) {
getAccountChooser(new OnClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int pos, long arg3) {
Intent intent = new Intent(activity,ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
intent.putExtra("uuid", aggregatedContacts.get(pos).getUuid());
startActivity(intent);
return true;
@Override
public void onClick(DialogInterface dialog, int which) {
contact.setAccount(accounts.get(which));
showIsMucDialogIfNeeded(contact);
}
}).show();
} else {
if (contact.getAccount()==null) {
contact.setAccount(accounts.get(0));
}
});
showIsMucDialogIfNeeded(contact);
}
}
protected AlertDialog getAccountChooser(OnClickListener listener) {
@ -329,4 +451,27 @@ public class NewConversationActivity extends XmppActivity {
}
}
}
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
this.isActionMode = true;
search.setEnabled(false);
}
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
this.isActionMode = false;
contactsView.clearChoices();
contactsView.requestLayout();
contactsView.post(new Runnable() {
@Override
public void run() {
contactsView.setChoiceMode(ListView.CHOICE_MODE_NONE);
}
});
search.setEnabled(true);
}
}

View file

@ -15,6 +15,7 @@ import java.security.SecureRandom;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
@ -66,6 +67,7 @@ public class XmppConnection implements Runnable {
private boolean shouldAuthenticate = true;
private Element streamFeatures;
private HashSet<String> discoFeatures = new HashSet<String>();
private List<String> discoItems = new ArrayList<String>();
private String streamId = null;
@ -550,7 +552,8 @@ public class XmppConnection implements Runnable {
tagWriter.writeStanzaAsync(enable);
}
sendInitialPresence();
sendServiceDiscovery();
sendServiceDiscoveryInfo();
sendServiceDiscoveryItems();
if (statusListener != null) {
statusListener.onStatusChanged(account);
}
@ -558,32 +561,45 @@ public class XmppConnection implements Runnable {
});
}
private void sendServiceDiscovery() {
private void sendServiceDiscoveryInfo() {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setAttribute("to", account.getServer());
Element query = new Element("query");
query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info");
iq.addChild(query);
iq.setTo(account.getServer());
iq.query("http://jabber.org/protocol/disco#info");
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.hasChild("query")) {
List<Element> elements = packet.findChild("query")
.getChildren();
List<Element> elements = packet.query().getChildren();
for (int i = 0; i < elements.size(); ++i) {
if (elements.get(i).getName().equals("feature")) {
discoFeatures.add(elements.get(i).getAttribute(
"var"));
}
}
}
if (discoFeatures.contains("urn:xmpp:carbons:2")) {
sendEnableCarbons();
}
}
});
}
private void sendServiceDiscoveryItems() {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
iq.setTo(account.getServer());
iq.query("http://jabber.org/protocol/disco#items");
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
List<Element> elements = packet.query().getChildren();
for (int i = 0; i < elements.size(); ++i) {
if (elements.get(i).getName().equals("item")) {
discoItems.add(elements.get(i).getAttribute(
"jid"));
}
}
}
});
}
private void sendEnableCarbons() {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
@ -754,4 +770,17 @@ public class XmppConnection implements Runnable {
public int getSentStanzas() {
return this.stanzasSent;
}
public String getMucServer() {
for(int i = 0; i < discoItems.size(); ++i) {
if (discoItems.get(i).contains("conference.")) {
return discoItems.get(i);
} else if (discoItems.get(i).contains("conf.")) {
return discoItems.get(i);
} else if (discoItems.get(i).contains("muc.")) {
return discoItems.get(i);
}
}
return null;
}
}

View file

@ -5,7 +5,7 @@ import eu.siacs.conversations.xml.Element;
public class MessagePacket extends AbstractStanza {
public static final int TYPE_CHAT = 0;
public static final int TYPE_UNKNOWN = 1;
public static final int TYPE_NO = 2;
public static final int TYPE_NORMAL = 2;
public static final int TYPE_GROUPCHAT = 3;
public static final int TYPE_ERROR = 4;
@ -46,9 +46,10 @@ public class MessagePacket extends AbstractStanza {
public int getType() {
String type = getAttribute("type");
if (type==null) {
return TYPE_NO;
}
if (type.equals("chat")) {
return TYPE_NORMAL;
} else if (type.equals("normal")) {
return TYPE_NORMAL;
} else if (type.equals("chat")) {
return TYPE_CHAT;
} else if (type.equals("groupchat")) {
return TYPE_GROUPCHAT;