aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Conversation.java18
-rw-r--r--src/main/java/eu/siacs/conversations/entities/MucOptions.java160
-rw-r--r--src/main/java/eu/siacs/conversations/generator/MessageGenerator.java4
-rw-r--r--src/main/java/eu/siacs/conversations/services/AvatarService.java2
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java171
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java49
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java14
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/XmppActivity.java59
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java9
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/forms/Data.java75
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/forms/Field.java50
-rw-r--r--src/main/res/values/strings.xml4
13 files changed, 480 insertions, 137 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 8003759d..4801fe12 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -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();
}
diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
index 4725bffa..2655fc44 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -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,46 +208,63 @@ 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() {
@@ -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() {
diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
index 65f776ff..ca5417e0 100644
--- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
@@ -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;
diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java
index b8154d65..1125859c 100644
--- a/src/main/java/eu/siacs/conversations/services/AvatarService.java
+++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java
@@ -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) {
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 89a3917c..b700da74 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -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;
@@ -270,7 +271,6 @@ public class XmppConnectionService extends Service {
}
};
private LruCache<String, Bitmap> mBitmapCache;
- private OnRenameListener renameListener = null;
private IqGenerator mIqGenerator = new IqGenerator(this);
public PgpEngine getPgpEngine() {
@@ -1052,10 +1052,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);
@@ -1273,10 +1269,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) {
@@ -1308,10 +1303,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);
@@ -1324,33 +1315,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();
@@ -1360,7 +1351,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();
@@ -1379,7 +1370,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);
@@ -1392,6 +1383,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)) {
@@ -1723,7 +1825,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);
}
@@ -2020,6 +2122,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;
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index c97f9e56..a966f77b 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -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() {
+ 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 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();
+ }
+
+ @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);
}
});
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 721ad9c3..0be3a957 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -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);
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index abfd0727..287d1636 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -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;
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index 2ff317a4..a9147fba 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -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;
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index f7a86802..dc895ead 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -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() {
diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java
new file mode 100644
index 00000000..ff9acb3f
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java
@@ -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;
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java
new file mode 100644
index 00000000..ee2c51a9
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java
@@ -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;
+ }
+}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 6881c7f9..1bb0ef75 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -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>