brought ad hoc conferences back. fixed #688 fixed #367

This commit is contained in:
iNPUTmice 2014-11-20 18:20:42 +01:00
parent e9948f6b84
commit 0ad6d0616f
13 changed files with 481 additions and 138 deletions

View File

@ -149,11 +149,19 @@ public class Conversation extends AbstractEntity {
}
public String getName() {
if (getMode() == MODE_MULTI && getMucOptions().getSubject() != null) {
return getMucOptions().getSubject();
} else if (getMode() == MODE_MULTI && bookmark != null
&& bookmark.getName() != null) {
return bookmark.getName();
if (getMode() == MODE_MULTI) {
if (getMucOptions().getSubject() != null) {
return getMucOptions().getSubject();
} else if (bookmark != null && bookmark.getName() != null) {
return bookmark.getName();
} else {
String generatedName = getMucOptions().createNameFromParticipants();
if (generatedName != null) {
return generatedName;
} else {
return getContactJid().getLocalpart();
}
}
} else {
return this.getContact().getDisplayName();
}

View File

@ -4,18 +4,20 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import android.annotation.SuppressLint;
import android.util.Log;
@SuppressLint("DefaultLocale")
public class MucOptions {
public static final int ERROR_NO_ERROR = 0;
public static final int ERROR_NICK_IN_USE = 1;
public static final int ERROR_ROOM_NOT_FOUND = 2;
public static final int ERROR_UNKNOWN = 2;
public static final int ERROR_PASSWORD_REQUIRED = 3;
public static final int ERROR_BANNED = 4;
public static final int ERROR_MEMBERS_ONLY = 5;
@ -25,8 +27,17 @@ public class MucOptions {
public static final String STATUS_CODE_BANNED = "301";
public static final String STATUS_CODE_KICKED = "307";
public interface OnRenameListener {
public void onRename(boolean success);
private interface OnEventListener {
public void onSuccess();
public void onFailure();
}
public interface OnRenameListener extends OnEventListener {
}
public interface OnJoinListener extends OnEventListener {
}
public class User {
@ -119,13 +130,13 @@ public class MucOptions {
private List<User> users = new CopyOnWriteArrayList<>();
private Conversation conversation;
private boolean isOnline = false;
private int error = ERROR_ROOM_NOT_FOUND;
private OnRenameListener renameListener = null;
private boolean aboutToRename = false;
private int error = ERROR_UNKNOWN;
private OnRenameListener onRenameListener = null;
private OnJoinListener onJoinListener = null;
private User self = new User();
private String subject = null;
private String joinnick;
private String password = null;
private boolean mNickChangingInProgress = false;
public MucOptions(Conversation conversation) {
this.account = conversation.getAccount();
@ -155,10 +166,11 @@ public class MucOptions {
final Jid from = packet.getFrom();
if (!from.isBareJid()) {
final String name = from.getResourcepart();
String type = packet.getAttribute("type");
final String type = packet.getAttribute("type");
final Element x = packet.findChild("x","http://jabber.org/protocol/muc#user");
final List<String> codes = getStatusCodes(x);
if (type == null) {
User user = new User();
Element x = packet.findChild("x","http://jabber.org/protocol/muc#user");
if (x != null) {
Element item = x.findChild("item");
if (item != null) {
@ -166,16 +178,16 @@ public class MucOptions {
user.setAffiliation(item.getAttribute("affiliation"));
user.setRole(item.getAttribute("role"));
user.setJid(item.getAttributeAsJid("jid"));
user.setName(name);
if (name.equals(this.joinnick)) {
if (codes.contains("110")) {
this.isOnline = true;
this.error = ERROR_NO_ERROR;
self = user;
if (aboutToRename) {
if (renameListener != null) {
renameListener.onRename(true);
}
aboutToRename = false;
if (mNickChangingInProgress) {
onRenameListener.onSuccess();
mNickChangingInProgress = false;
} else if (this.onJoinListener != null) {
this.onJoinListener.onSuccess();
this.onJoinListener = null;
}
} else {
addUser(user);
@ -196,48 +208,65 @@ public class MucOptions {
}
}
}
} else if (type.equals("unavailable") && name.equals(this.joinnick)) {
Element x = packet.findChild("x",
"http://jabber.org/protocol/muc#user");
if (x != null) {
Element status = x.findChild("status");
if (status != null) {
String code = status.getAttribute("code");
if (STATUS_CODE_KICKED.equals(code)) {
this.isOnline = false;
this.error = KICKED_FROM_ROOM;
} else if (STATUS_CODE_BANNED.equals(code)) {
this.isOnline = false;
this.error = ERROR_BANNED;
}
}
} else if (type.equals("unavailable") && codes.contains("110")) {
if (codes.contains("303")) {
this.mNickChangingInProgress = true;
} else if (codes.contains(STATUS_CODE_KICKED)) {
setError(KICKED_FROM_ROOM);
} else if (codes.contains(STATUS_CODE_BANNED)) {
setError(ERROR_BANNED);
} else {
setError(ERROR_UNKNOWN);
}
} else if (type.equals("unavailable")) {
deleteUser(packet.getAttribute("from").split("/", 2)[1]);
deleteUser(name);
} else if (type.equals("error")) {
Element error = packet.findChild("error");
if (error != null && error.hasChild("conflict")) {
if (aboutToRename) {
if (renameListener != null) {
renameListener.onRename(false);
if (isOnline) {
if (onRenameListener != null) {
onRenameListener.onFailure();
}
aboutToRename = false;
this.setJoinNick(getActualNick());
} else {
this.error = ERROR_NICK_IN_USE;
setError(ERROR_NICK_IN_USE);
}
} else if (error != null && error.hasChild("not-authorized")) {
this.error = ERROR_PASSWORD_REQUIRED;
setError(ERROR_PASSWORD_REQUIRED);
} else if (error != null && error.hasChild("forbidden")) {
this.error = ERROR_BANNED;
} else if (error != null
&& error.hasChild("registration-required")) {
this.error = ERROR_MEMBERS_ONLY;
setError(ERROR_BANNED);
} else if (error != null && error.hasChild("registration-required")) {
setError(ERROR_MEMBERS_ONLY);
} else {
setError(ERROR_UNKNOWN);
}
}
}
}
private void setError(int error) {
this.isOnline = false;
this.error = error;
if (onJoinListener != null) {
onJoinListener.onFailure();
onJoinListener = null;
}
}
private List<String> getStatusCodes(Element x) {
List<String> codes = new ArrayList<String>();
if (x != null) {
for(Element child : x.getChildren()) {
if (child.getName().equals("status")) {
String code = child.getAttribute("code");
if (code!=null) {
codes.add(code);
}
}
}
}
return codes;
}
public List<User> getUsers() {
return this.users;
}
@ -263,10 +292,6 @@ public class MucOptions {
}
}
public void setJoinNick(String nick) {
this.joinnick = nick;
}
public boolean online() {
return this.isOnline;
}
@ -276,11 +301,11 @@ public class MucOptions {
}
public void setOnRenameListener(OnRenameListener listener) {
this.renameListener = listener;
this.onRenameListener = listener;
}
public OnRenameListener getOnRenameListener() {
return this.renameListener;
public void setOnJoinListener(OnJoinListener listener) {
this.onJoinListener = listener;
}
public void setOffline() {
@ -301,8 +326,28 @@ public class MucOptions {
return this.subject;
}
public void flagAboutToRename() {
this.aboutToRename = true;
public String createNameFromParticipants() {
if (users.size() >= 2) {
List<String> names = new ArrayList<String>();
for (User user : users) {
Contact contact = user.getContact();
if (contact != null && !contact.getDisplayName().isEmpty()) {
names.add(contact.getDisplayName().split("\\s+")[0]);
} else {
names.add(user.getName());
}
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < names.size(); ++i) {
builder.append(names.get(i));
if (i != names.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
} else {
return null;
}
}
public long[] getPgpKeyIds() {
@ -337,10 +382,9 @@ public class MucOptions {
return true;
}
public Jid getJoinJid() {
public Jid createJoinJid(String nick) {
try {
return Jid.fromString(this.conversation.getContactJid().toBareJid().toString() + "/"
+ this.joinnick);
return Jid.fromString(this.conversation.getContactJid().toBareJid().toString() + "/"+nick);
} catch (final InvalidJidException e) {
return null;
}
@ -356,8 +400,7 @@ public class MucOptions {
}
public String getPassword() {
this.password = conversation
.getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
this.password = conversation.getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
if (this.password == null && conversation.getBookmark() != null
&& conversation.getBookmark().getPassword() != null) {
return conversation.getBookmark().getPassword();
@ -372,8 +415,7 @@ public class MucOptions {
} else {
this.password = password;
}
conversation
.setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password);
conversation.setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password);
}
public Conversation getConversation() {

View File

@ -153,14 +153,14 @@ public class MessageGenerator extends AbstractGenerator {
return packet;
}
public MessagePacket invite(Conversation conversation, String contact) {
public MessagePacket invite(Conversation conversation, Jid contact) {
MessagePacket packet = new MessagePacket();
packet.setTo(conversation.getContactJid().toBareJid());
packet.setFrom(conversation.getAccount().getJid());
Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
Element invite = new Element("invite");
invite.setAttribute("to", contact);
invite.setAttribute("to", contact.toBareJid().toString());
x.addChild(invite);
packet.addChild(x);
return packet;

View File

@ -274,7 +274,7 @@ public class AvatarService {
}
}
}
String name = user.getName();
String name = contact != null ? contact.getDisplayName() : user.getName();
String letter;
int color;
if (name.length() > 0) {

View File

@ -35,6 +35,7 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -273,7 +274,6 @@ public class XmppConnectionService extends Service {
}
};
private LruCache<String, Bitmap> mBitmapCache;
private OnRenameListener renameListener = null;
private IqGenerator mIqGenerator = new IqGenerator(this);
public PgpEngine getPgpEngine() {
@ -1055,10 +1055,6 @@ public class XmppConnectionService extends Service {
updateConversationUi();
}
public int getConversationCount() {
return this.databaseBackend.getConversationCount();
}
public void createAccount(Account account) {
account.initOtrEngine(this);
databaseBackend.createAccount(account);
@ -1276,10 +1272,9 @@ public class XmppConnectionService extends Service {
Log.d(Config.LOGTAG,
"joining conversation " + conversation.getContactJid());
String nick = conversation.getMucOptions().getProposedNick();
conversation.getMucOptions().setJoinNick(nick);
Jid joinJid = conversation.getMucOptions().createJoinJid(nick);
PresencePacket packet = new PresencePacket();
final Jid joinJid = conversation.getMucOptions().getJoinJid();
packet.setTo(conversation.getMucOptions().getJoinJid());
packet.setTo(joinJid);
Element x = new Element("x");
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
if (conversation.getMucOptions().getPassword() != null) {
@ -1311,10 +1306,6 @@ public class XmppConnectionService extends Service {
}
}
public void setOnRenameListener(OnRenameListener listener) {
this.renameListener = listener;
}
public void providePasswordForMuc(Conversation conversation, String password) {
if (conversation.getMode() == Conversation.MODE_MULTI) {
conversation.getMucOptions().setPassword(password);
@ -1327,33 +1318,33 @@ public class XmppConnectionService extends Service {
}
}
public void renameInMuc(final Conversation conversation, final String nick) {
public void renameInMuc(final Conversation conversation, final String nick, final UiCallback<Conversation> callback) {
final MucOptions options = conversation.getMucOptions();
options.setJoinNick(nick);
final Jid joinJid = options.createJoinJid(nick);
if (options.online()) {
Account account = conversation.getAccount();
options.setOnRenameListener(new OnRenameListener() {
@Override
public void onRename(boolean success) {
if (renameListener != null) {
renameListener.onRename(success);
}
if (success) {
conversation.setContactJid(conversation.getMucOptions()
.getJoinJid());
databaseBackend.updateConversation(conversation);
Bookmark bookmark = conversation.getBookmark();
if (bookmark != null) {
bookmark.setNick(nick);
pushBookmarks(bookmark.getAccount());
}
public void onSuccess() {
conversation.setContactJid(joinJid);
databaseBackend.updateConversation(conversation);
Bookmark bookmark = conversation.getBookmark();
if (bookmark != null) {
bookmark.setNick(nick);
pushBookmarks(bookmark.getAccount());
}
callback.success(conversation);
}
@Override
public void onFailure() {
callback.error(R.string.nick_in_use,conversation);
}
});
options.flagAboutToRename();
PresencePacket packet = new PresencePacket();
packet.setTo(options.getJoinJid());
packet.setTo(joinJid);
packet.setFrom(conversation.getAccount().getJid());
String sig = account.getPgpSignature();
@ -1363,7 +1354,7 @@ public class XmppConnectionService extends Service {
}
sendPresencePacket(account, packet);
} else {
conversation.setContactJid(options.getJoinJid());
conversation.setContactJid(joinJid);
databaseBackend.updateConversation(conversation);
if (conversation.getAccount().getStatus() == Account.State.ONLINE) {
Bookmark bookmark = conversation.getBookmark();
@ -1382,7 +1373,7 @@ public class XmppConnectionService extends Service {
account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.State.ONLINE) {
PresencePacket packet = new PresencePacket();
packet.setTo(conversation.getMucOptions().getJoinJid());
packet.setTo(conversation.getContactJid());
packet.setFrom(conversation.getAccount().getJid());
packet.setAttribute("type", "unavailable");
sendPresencePacket(conversation.getAccount(), packet);
@ -1395,6 +1386,117 @@ public class XmppConnectionService extends Service {
}
}
private String findConferenceServer(final Account account) {
String server;
if (account.getXmppConnection() != null) {
server = account.getXmppConnection().getMucServer();
if (server != null) {
return server;
}
}
for(Account other : getAccounts()) {
if (other != account && other.getXmppConnection() != null) {
server = other.getXmppConnection().getMucServer();
if (server != null) {
return server;
}
}
}
return null;
}
public void createAdhocConference(final Account account, final List<Jid> jids, final UiCallback<Conversation> callback) {
Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": creating adhoc conference with "+ jids.toString());
if (account.getStatus() == Account.State.ONLINE) {
try {
String server = findConferenceServer(account);
if (server == null) {
if (callback != null) {
callback.error(R.string.no_conference_server_found,null);
}
return;
}
String name = new BigInteger(75,getRNG()).toString(32);
Jid jid = Jid.fromParts(name,server,null);
final Conversation conversation = findOrCreateConversation(account, jid, true);
joinMuc(conversation);
Bundle options = new Bundle();
options.putString("muc#roomconfig_persistentroom", "1");
options.putString("muc#roomconfig_membersonly", "1");
options.putString("muc#roomconfig_publicroom", "0");
options.putString("muc#roomconfig_whois", "anyone");
pushConferenceConfiguration(conversation, options, new OnConferenceOptionsPushed() {
@Override
public void onPushSucceeded() {
for(Jid invite : jids) {
invite(conversation,invite);
}
if (callback != null) {
callback.success(conversation);
}
}
@Override
public void onPushFailed() {
if (callback != null) {
callback.error(R.string.conference_creation_failed, conversation);
}
}
});
} catch (InvalidJidException e) {
if (callback != null) {
callback.error(R.string.conference_creation_failed, null);
}
}
} else {
if (callback != null) {
callback.error(R.string.not_connected_try_again,null);
}
}
}
public void pushConferenceConfiguration(final Conversation conversation,final Bundle options, final OnConferenceOptionsPushed callback) {
IqPacket request = new IqPacket(IqPacket.TYPE_GET);
request.setTo(conversation.getContactJid().toBareJid());
request.query("http://jabber.org/protocol/muc#owner");
sendIqPacket(conversation.getAccount(),request,new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() != IqPacket.TYPE_ERROR) {
Data data = Data.parse(packet.query().findChild("x", "jabber:x:data"));
for (Field field : data.getFields()) {
if (options.containsKey(field.getName())) {
field.setValue(options.getString(field.getName()));
}
}
data.submit();
IqPacket set = new IqPacket(IqPacket.TYPE_SET);
set.setTo(conversation.getContactJid().toBareJid());
set.query("http://jabber.org/protocol/muc#owner").addChild(data);
sendIqPacket(account, set, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE_RESULT) {
if (callback != null) {
callback.onPushSucceeded();
}
} else {
if (callback != null) {
callback.onPushFailed();
}
}
}
});
} else {
if (callback != null) {
callback.onPushFailed();
}
}
}
});
}
public void disconnect(Account account, boolean force) {
if ((account.getStatus() == Account.State.ONLINE)
|| (account.getStatus() == Account.State.DISABLED)) {
@ -1726,7 +1828,7 @@ public class XmppConnectionService extends Service {
}).start();
}
public void invite(Conversation conversation, String contact) {
public void invite(Conversation conversation, Jid contact) {
MessagePacket packet = mMessageGenerator.invite(conversation, contact);
sendMessagePacket(conversation.getAccount(), packet);
}
@ -2023,6 +2125,11 @@ public class XmppConnectionService extends Service {
public void onRosterUpdate();
}
private interface OnConferenceOptionsPushed {
public void onPushSucceeded();
public void onPushFailed();
}
public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() {
return XmppConnectionService.this;

View File

@ -34,7 +34,7 @@ import eu.siacs.conversations.entities.MucOptions.User;
import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnRenameListener {
public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate {
public static final String ACTION_VIEW_MUC = "view_muc";
private Conversation mConversation;
private OnClickListener inviteListener = new OnClickListener() {
@ -57,26 +57,34 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
private List<User> users = new ArrayList<>();
private User mSelectedUser = null;
@Override
public void onRename(final boolean success) {
runOnUiThread(new Runnable() {
@Override
public void run() {
populateView();
if (success) {
Toast.makeText(
ConferenceDetailsActivity.this,
getString(R.string.your_nick_has_been_changed),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ConferenceDetailsActivity.this,
getString(R.string.nick_in_use),
Toast.LENGTH_SHORT).show();
private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() {
@Override
public void success(Conversation object) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(ConferenceDetailsActivity.this,getString(R.string.your_nick_has_been_changed),Toast.LENGTH_SHORT).show();
populateView();
}
}
});
}
});
}
@Override
public void error(final int errorCode, Conversation object) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(ConferenceDetailsActivity.this,getString(errorCode),Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void userInputRequried(PendingIntent pi, Conversation object) {
}
};
@Override
public void onConversationUpdate() {
@ -114,8 +122,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
@Override
public void onValueEdited(String value) {
xmppConnectionService.renameInMuc(mConversation,
value);
xmppConnectionService.renameInMuc(mConversation,value,renameCallback);
}
});
}

View File

@ -225,6 +225,18 @@ public class ConversationActivity extends XmppActivity implements
}
}
@Override
public void switchToConversation(Conversation conversation) {
setSelectedConversation(conversation);
runOnUiThread(new Runnable() {
@Override
public void run() {
ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation());
openConversation();
}
});
}
public void openConversation() {
ActionBar ab = getActionBar();
if (ab != null) {
@ -286,7 +298,7 @@ public class ConversationActivity extends XmppActivity implements
menuAttach.setVisible(false);
} else {
menuMucDetails.setVisible(false);
menuInviteContact.setVisible(false);
menuInviteContact.setTitle(R.string.conference_with);
}
if (this.getSelectedConversation().isMuted()) {
menuMute.setVisible(false);

View File

@ -553,7 +553,7 @@ public class ConversationFragment extends Fragment {
showSnackbar(R.string.nick_in_use, R.string.edit,
clickToMuc);
break;
case MucOptions.ERROR_ROOM_NOT_FOUND:
case MucOptions.ERROR_UNKNOWN:
showSnackbar(R.string.conference_not_found,
R.string.leave, leaveMuc);
break;

View File

@ -42,6 +42,7 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
@ -54,6 +55,7 @@ import net.java.otr4j.session.SessionID;
import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
@ -240,9 +242,6 @@ public abstract class XmppActivity extends Activity {
if (this instanceof XmppConnectionService.OnRosterUpdate) {
this.xmppConnectionService.setOnRosterUpdateListener((XmppConnectionService.OnRosterUpdate) this);
}
if (this instanceof MucOptions.OnRenameListener) {
this.xmppConnectionService.setOnRenameListener((MucOptions.OnRenameListener) this);
}
}
protected void unregisterListeners() {
@ -255,9 +254,6 @@ public abstract class XmppActivity extends Activity {
if (this instanceof XmppConnectionService.OnRosterUpdate) {
this.xmppConnectionService.removeOnRosterUpdateListener();
}
if (this instanceof MucOptions.OnRenameListener) {
this.xmppConnectionService.setOnRenameListener(null);
}
}
public boolean onOptionsItemSelected(MenuItem item) {
@ -603,18 +599,53 @@ public abstract class XmppActivity extends Activity {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INVITE_TO_CONVERSATION
&& resultCode == RESULT_OK) {
String contactJid = data.getStringExtra("contact");
String conversationUuid = data.getStringExtra("conversation");
Conversation conversation = xmppConnectionService
.findConversationByUuid(conversationUuid);
if (conversation.getMode() == Conversation.MODE_MULTI) {
xmppConnectionService.invite(conversation, contactJid);
try {
Jid jid = Jid.fromString(data.getStringExtra("contact"));
String conversationUuid = data.getStringExtra("conversation");
Conversation conversation = xmppConnectionService
.findConversationByUuid(conversationUuid);
if (conversation.getMode() == Conversation.MODE_MULTI) {
xmppConnectionService.invite(conversation, jid);
} else {
List<Jid> jids = new ArrayList<Jid>();
jids.add(conversation.getContactJid().toBareJid());
jids.add(jid);
xmppConnectionService.createAdhocConference(conversation.getAccount(), jids, adhocCallback);
}
} catch (final InvalidJidException ignored) {
}
Log.d(Config.LOGTAG, "inviting " + contactJid + " to "
+ conversation.getName());
}
}
private UiCallback<Conversation> adhocCallback = new UiCallback<Conversation>() {
@Override
public void success(final Conversation conversation) {
switchToConversation(conversation);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(XmppActivity.this,R.string.conference_created,Toast.LENGTH_LONG).show();
}
});
}
@Override
public void error(final int errorCode, Conversation object) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(XmppActivity.this,errorCode,Toast.LENGTH_LONG).show();
}
});
}
@Override
public void userInputRequried(PendingIntent pi, Conversation object) {
}
};
public int getSecondaryTextColor() {
return this.mSecondaryTextColor;
}

View File

@ -1049,7 +1049,14 @@ public class XmppConnection implements Runnable {
}
public String getMucServer() {
return findDiscoItemByFeature("http://jabber.org/protocol/muc");
final List<String> items = new ArrayList<>();
for (Entry<String, List<String>> cursor : disco.entrySet()) {
final List<String> value = cursor.getValue();
if (value.contains("http://jabber.org/protocol/muc") && !value.contains("jabber:iq:gateway")) {
return cursor.getKey();
}
}
return null;
}
public int getTimeToNextAttempt() {

View File

@ -0,0 +1,75 @@
package eu.siacs.conversations.xmpp.forms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import eu.siacs.conversations.xml.Element;
public class Data extends Element {
public Data() {
super("x");
this.setAttribute("xmlns","jabber:x:data");
}
public List<Field> getFields() {
ArrayList<Field> fields = new ArrayList<Field>();
for(Element child : getChildren()) {
if (child.getName().equals("field")) {
fields.add(Field.parse(child));
}
}
return fields;
}
public Field getFieldByName(String needle) {
for(Element child : getChildren()) {
if (child.getName().equals("field") && needle.equals(child.getAttribute("var"))) {
return Field.parse(child);
}
}
return null;
}
public void put(String name, String value) {
Field field = getFieldByName(name);
if (field == null) {
field = new Field(name);
}
field.setValue(value);
}
public void put(String name, Collection<String> values) {
Field field = getFieldByName(name);
if (field == null) {
field = new Field(name);
}
field.setValues(values);
}
public void submit() {
this.setAttribute("type","submit");
removeNonFieldChildren();
for(Field field : getFields()) {
field.removeNonValueChildren();
}
}
private void removeNonFieldChildren() {
for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
Element element = iterator.next();
if (!element.getName().equals("field")) {
iterator.remove();
}
}
}
public static Data parse(Element element) {
Data data = new Data();
data.setAttributes(element.getAttributes());
data.setChildren(element.getChildren());
return data;
}
}

View File

@ -0,0 +1,50 @@
package eu.siacs.conversations.xmpp.forms;
import java.util.Collection;
import java.util.Iterator;
import eu.siacs.conversations.xml.Element;
public class Field extends Element {
public Field(String name) {
super("field");
this.setAttribute("var",name);
}
private Field() {
super("field");
}
public String getName() {
return this.getAttribute("var");
}
public void setValue(String value) {
this.children.clear();
this.addChild("value").setContent(value);
}
public void setValues(Collection<String> values) {
this.children.clear();
for(String value : values) {
this.addChild("value").setContent(value);
}
}
public void removeNonValueChildren() {
for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
Element element = iterator.next();
if (!element.getName().equals("value")) {
iterator.remove();
}
}
}
public static Field parse(Element element) {
Field field = new Field();
field.setAttributes(element.getAttributes());
field.setChildren(element.getChildren());
return field;
}
}

View File

@ -352,4 +352,8 @@
<string name="pref_show_dynamic_tags">Show dynamic tags</string>
<string name="pref_show_dynamic_tags_summary">Display read-only tags underneath contacts</string>
<string name="enable_notifications">Enable notifications</string>
<string name="conference_with">Create conference with…</string>
<string name="no_conference_server_found">No conference server found</string>
<string name="conference_creation_failed">Conference creation failed!</string>
<string name="conference_created">Conference created!</string>
</resources>