aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs')
-rw-r--r--src/eu/siacs/conversations/crypto/PgpEngine.java3
-rw-r--r--src/eu/siacs/conversations/entities/Account.java21
-rw-r--r--src/eu/siacs/conversations/entities/Bookmark.java125
-rw-r--r--src/eu/siacs/conversations/entities/Contact.java58
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java34
-rw-r--r--src/eu/siacs/conversations/entities/ListItem.java10
-rw-r--r--src/eu/siacs/conversations/generator/MessageGenerator.java24
-rw-r--r--src/eu/siacs/conversations/generator/PresenceGenerator.java43
-rw-r--r--src/eu/siacs/conversations/parser/IqParser.java89
-rw-r--r--src/eu/siacs/conversations/parser/MessageParser.java177
-rw-r--r--src/eu/siacs/conversations/parser/PresenceParser.java38
-rw-r--r--src/eu/siacs/conversations/persistance/DatabaseBackend.java4
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java609
-rw-r--r--src/eu/siacs/conversations/ui/ContactDetailsActivity.java41
-rw-r--r--src/eu/siacs/conversations/ui/ContactsActivity.java598
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java62
-rw-r--r--src/eu/siacs/conversations/ui/ConversationFragment.java64
-rw-r--r--src/eu/siacs/conversations/ui/EditAccount.java23
-rw-r--r--src/eu/siacs/conversations/ui/ManageAccountActivity.java562
-rw-r--r--src/eu/siacs/conversations/ui/MucDetailsActivity.java9
-rw-r--r--src/eu/siacs/conversations/ui/OnAccountListChangedListener.java5
-rw-r--r--src/eu/siacs/conversations/ui/OnConversationListChangedListener.java5
-rw-r--r--src/eu/siacs/conversations/ui/ShareWithActivity.java4
-rw-r--r--src/eu/siacs/conversations/ui/StartConversation.java548
-rw-r--r--src/eu/siacs/conversations/ui/XmppActivity.java20
-rw-r--r--src/eu/siacs/conversations/utils/KnownHostsAdapter.java69
-rw-r--r--src/eu/siacs/conversations/utils/UIHelper.java16
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java23
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java11
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java8
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java1
31 files changed, 1859 insertions, 1445 deletions
diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java
index c0d8ca07..2d0c56e1 100644
--- a/src/eu/siacs/conversations/crypto/PgpEngine.java
+++ b/src/eu/siacs/conversations/crypto/PgpEngine.java
@@ -98,8 +98,7 @@ public class PgpEngine {
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
PgpEngine.this.mXmppConnectionService
.updateMessage(message);
- PgpEngine.this.mXmppConnectionService.updateUi(
- message.getConversation(), false);
+ PgpEngine.this.mXmppConnectionService.updateConversationUi();
callback.success(message);
return;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java
index a73d49f9..ac62cf7b 100644
--- a/src/eu/siacs/conversations/entities/Account.java
+++ b/src/eu/siacs/conversations/entities/Account.java
@@ -1,6 +1,8 @@
package eu.siacs.conversations.entities;
import java.security.interfaces.DSAPublicKey;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
@@ -67,6 +69,8 @@ public class Account extends AbstractEntity{
private String otrFingerprint;
private Roster roster = null;
+
+ private List<Bookmark> bookmarks = new ArrayList<Bookmark>();
public Account() {
this.uuid = "0";
@@ -297,4 +301,21 @@ public class Account extends AbstractEntity{
}
return this.roster;
}
+
+ public void setBookmarks(List<Bookmark> bookmarks) {
+ this.bookmarks = bookmarks;
+ }
+
+ public List<Bookmark> getBookmarks() {
+ return this.bookmarks;
+ }
+
+ public boolean hasBookmarkFor(String conferenceJid) {
+ for(Bookmark bmark : this.bookmarks) {
+ if (bmark.getJid().equals(conferenceJid)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/eu/siacs/conversations/entities/Bookmark.java b/src/eu/siacs/conversations/entities/Bookmark.java
new file mode 100644
index 00000000..c4e151cb
--- /dev/null
+++ b/src/eu/siacs/conversations/entities/Bookmark.java
@@ -0,0 +1,125 @@
+package eu.siacs.conversations.entities;
+
+import java.util.Locale;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xml.Element;
+
+public class Bookmark implements ListItem {
+
+ private Account account;
+ private String jid;
+ private String nick;
+ private String name;
+ private boolean autojoin;
+ private Conversation mJoinedConversation;
+
+ public Bookmark(Account account, String jid) {
+ this.account = account;
+ this.jid = jid;
+ }
+
+ public static Bookmark parse(Element element, Account account) {
+ Bookmark bookmark = new Bookmark(account,element.getAttribute("jid"));
+ bookmark.setName(element.getAttribute("name"));
+ String autojoin = element.getAttribute("autojoin");
+ if (autojoin!=null && (autojoin.equals("true")||autojoin.equals("1"))) {
+ bookmark.setAutojoin(true);
+ } else {
+ bookmark.setAutojoin(false);
+ }
+ Element nick = element.findChild("nick");
+ if (nick!=null) {
+ bookmark.setNick(nick.getContent());
+ }
+ return bookmark;
+ }
+
+ public void setAutojoin(boolean autojoin) {
+ this.autojoin = autojoin;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNick(String nick) {
+ this.nick = nick;
+ }
+
+ @Override
+ public int compareTo(ListItem another) {
+ return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
+ }
+
+ @Override
+ public String getDisplayName() {
+ if (this.mJoinedConversation!=null && (this.mJoinedConversation.getMucOptions().getSubject() != null)) {
+ return this.mJoinedConversation.getMucOptions().getSubject();
+ } else if (name!=null) {
+ return name;
+ } else {
+ return this.jid.split("@")[0];
+ }
+ }
+
+ @Override
+ public String getJid() {
+ return this.jid.toLowerCase(Locale.US);
+ }
+
+ public String getNick() {
+ return this.nick;
+ }
+
+ public boolean autojoin() {
+ return autojoin;
+ }
+
+ public boolean match(String needle) {
+ return needle == null
+ || getJid().contains(needle.toLowerCase(Locale.US))
+ || getDisplayName().toLowerCase(Locale.US)
+ .contains(needle.toLowerCase(Locale.US));
+ }
+
+ public Account getAccount() {
+ return this.account;
+ }
+
+ @Override
+ public Bitmap getImage(int dpSize, Context context) {
+ if (this.mJoinedConversation==null) {
+ return UIHelper.getContactPicture(getDisplayName(), dpSize, context, false);
+ } else {
+ return UIHelper.getContactPicture(this.mJoinedConversation, dpSize, context, false);
+ }
+ }
+
+ public void setConversation(Conversation conversation) {
+ this.mJoinedConversation = conversation;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Element toElement() {
+ Element element = new Element("conference");
+ element.setAttribute("jid", this.getJid());
+ if (this.getName() != null) {
+ element.setAttribute("name", this.getName());
+ }
+ if (this.autojoin) {
+ element.setAttribute("autojoin", "true");
+ } else {
+ element.setAttribute("autojoin", "false");
+ }
+ if (this.nick != null) {
+ element.addChild("nick").setContent(this.nick);
+ }
+ return element;
+ }
+}
diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java
index 50d7af8b..8f8e38a5 100644
--- a/src/eu/siacs/conversations/entities/Contact.java
+++ b/src/eu/siacs/conversations/entities/Contact.java
@@ -8,11 +8,14 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element;
import android.content.ContentValues;
+import android.content.Context;
import android.database.Cursor;
+import android.graphics.Bitmap;
-public class Contact {
+public class Contact implements ListItem {
public static final String TABLENAME = "contacts";
public static final String SYSTEMNAME = "systemname";
@@ -37,7 +40,7 @@ public class Contact {
protected Account account;
protected boolean inRoster = true;
-
+
public Lastseen lastseen = new Lastseen();
public Contact(String account, String systemName, String serverName,
@@ -83,8 +86,10 @@ public class Contact {
}
public boolean match(String needle) {
- return (jid.toLowerCase().contains(needle.toLowerCase()) || (getDisplayName()
- .toLowerCase().contains(needle.toLowerCase())));
+ return needle == null
+ || jid.contains(needle.toLowerCase())
+ || getDisplayName().toLowerCase()
+ .contains(needle.toLowerCase());
}
public ContentValues getContentValues() {
@@ -127,27 +132,7 @@ public class Contact {
public Account getAccount() {
return this.account;
}
-
- public boolean couldBeMuc() {
- String[] split = this.getJid().split("@");
- if (split.length != 2) {
- return false;
- } else {
- String[] domainParts = split[1].split("\\.");
- if (domainParts.length < 3) {
- return false;
- } else {
- return (domainParts[0].equals("conf")
- || domainParts[0].equals("conference")
- || domainParts[0].equals("room")
- || domainParts[0].equals("muc")
- || domainParts[0].equals("chat")
- || domainParts[0].equals("sala")
- || domainParts[0].equals("salas"));
- }
- }
- }
-
+
public Presences getPresences() {
return this.presences;
}
@@ -270,9 +255,11 @@ public class Contact {
} else if (subscription.equals("from")) {
this.resetOption(Contact.Options.TO);
this.setOption(Contact.Options.FROM);
+ this.resetOption(Contact.Options.PREEMPTIVE_GRANT);
} else if (subscription.equals("both")) {
this.setOption(Contact.Options.TO);
this.setOption(Contact.Options.FROM);
+ this.resetOption(Contact.Options.PREEMPTIVE_GRANT);
} else if (subscription.equals("none")) {
this.resetOption(Contact.Options.FROM);
this.resetOption(Contact.Options.TO);
@@ -308,9 +295,28 @@ public class Contact {
public static final int DIRTY_PUSH = 6;
public static final int DIRTY_DELETE = 7;
}
-
+
public class Lastseen {
public long time = 0;
public String presence = null;
}
+
+ @Override
+ public int compareTo(ListItem another) {
+ return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
+ }
+
+ public String getServer() {
+ String[] split = getJid().split("@");
+ if (split.length >= 2) {
+ return split[1];
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Bitmap getImage(int dpSize, Context context) {
+ return UIHelper.getContactPicture(this, dpSize, context, false);
+ }
}
diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index c207a5c9..70752adc 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -4,8 +4,6 @@ import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
import java.util.List;
-import eu.siacs.conversations.services.XmppConnectionService;
-
import net.java.otr4j.OtrException;
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
import net.java.otr4j.crypto.OtrCryptoException;
@@ -66,6 +64,8 @@ public class Conversation extends AbstractEntity {
private boolean otrSessionNeedsStarting = false;
+ private Bookmark bookmark;
+
public Conversation(String name, Account account, String contactJid,
int mode) {
this(java.util.UUID.randomUUID().toString(), name, null, account
@@ -117,14 +117,11 @@ public class Conversation extends AbstractEntity {
this.messages.get(i).markRead();
}
}
-
- public void markRead(XmppConnectionService service) {
- markRead();
- if (service.confirmMessages() && this.latestMarkableMessageId != null) {
- service.sendConfirmMessage(getAccount(), getContactJid(),
- this.latestMarkableMessageId);
- this.latestMarkableMessageId = null;
- }
+
+ public String popLatestMarkableMessageId() {
+ String id = this.latestMarkableMessageId;
+ this.latestMarkableMessageId = null;
+ return id;
}
public Message getLatestMessage() {
@@ -147,6 +144,8 @@ public class Conversation extends AbstractEntity {
if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null)
&& useSubject) {
return getMucOptions().getSubject();
+ } else if (getMode() == MODE_MULTI && bookmark!=null && bookmark.getName() != null) {
+ return bookmark.getName();
} else {
return this.getContact().getDisplayName();
}
@@ -380,4 +379,19 @@ public class Conversation extends AbstractEntity {
public byte[] getSymmetricKey() {
return this.symmetricKey;
}
+
+ public void setBookmark(Bookmark bookmark) {
+ this.bookmark = bookmark;
+ this.bookmark.setConversation(this);
+ }
+
+ public void deregisterWithBookmark() {
+ if (this.bookmark != null) {
+ this.bookmark.setConversation(null);
+ }
+ }
+
+ public Bookmark getBookmark() {
+ return this.bookmark;
+ }
}
diff --git a/src/eu/siacs/conversations/entities/ListItem.java b/src/eu/siacs/conversations/entities/ListItem.java
new file mode 100644
index 00000000..c89c85d9
--- /dev/null
+++ b/src/eu/siacs/conversations/entities/ListItem.java
@@ -0,0 +1,10 @@
+package eu.siacs.conversations.entities;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+public interface ListItem extends Comparable<ListItem> {
+ public String getDisplayName();
+ public String getJid();
+ public Bitmap getImage(int dpSize, Context context);
+}
diff --git a/src/eu/siacs/conversations/generator/MessageGenerator.java b/src/eu/siacs/conversations/generator/MessageGenerator.java
index 28504b21..5a216a7e 100644
--- a/src/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/eu/siacs/conversations/generator/MessageGenerator.java
@@ -42,7 +42,7 @@ public class MessageGenerator {
delay.setAttribute("stamp", mDateFormat.format(date));
}
- public MessagePacket generateOtrChat(Message message) throws OtrException {
+ public MessagePacket generateOtrChat(Message message) {
return generateOtrChat(message, false);
}
@@ -106,4 +106,26 @@ public class MessageGenerator {
packet.setType(MessagePacket.TYPE_ERROR);
return packet;
}
+
+ public MessagePacket confirm(Account account, String to, String id) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_NORMAL);
+ packet.setTo(to);
+ packet.setFrom(account.getFullJid());
+ Element received = packet.addChild("displayed",
+ "urn:xmpp:chat-markers:0");
+ received.setAttribute("id", id);
+ return packet;
+ }
+
+ public MessagePacket conferenceSubject(Conversation conversation,String subject) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_GROUPCHAT);
+ packet.setTo(conversation.getContactJid().split("/")[0]);
+ Element subjectChild = new Element("subject");
+ subjectChild.setContent(subject);
+ packet.addChild(subjectChild);
+ packet.setFrom(conversation.getAccount().getJid());
+ return packet;
+ }
}
diff --git a/src/eu/siacs/conversations/generator/PresenceGenerator.java b/src/eu/siacs/conversations/generator/PresenceGenerator.java
new file mode 100644
index 00000000..a301392e
--- /dev/null
+++ b/src/eu/siacs/conversations/generator/PresenceGenerator.java
@@ -0,0 +1,43 @@
+package eu.siacs.conversations.generator;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
+
+public class PresenceGenerator {
+
+ private PresencePacket subscription(String type, Contact contact) {
+ PresencePacket packet = new PresencePacket();
+ packet.setAttribute("type", type);
+ packet.setAttribute("to", contact.getJid());
+ packet.setAttribute("from", contact.getAccount().getJid());
+ return packet;
+ }
+
+ public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
+ return subscription("subscribe", contact);
+ }
+
+ public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
+ return subscription("unsubscribe", contact);
+ }
+
+ public PresencePacket stopPresenceUpdatesTo(Contact contact) {
+ return subscription("unsubscribed", contact);
+ }
+
+ public PresencePacket sendPresenceUpdatesTo(Contact contact) {
+ return subscription("subscribed", contact);
+ }
+
+ public PresencePacket sendPresence(Account account) {
+ PresencePacket packet = new PresencePacket();
+ packet.setAttribute("from", account.getFullJid());
+ String sig = account.getPgpSignature();
+ if (sig != null) {
+ packet.addChild("status").setContent("online");
+ packet.addChild("x", "jabber:x:signed").setContent(sig);
+ }
+ return packet;
+ }
+} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/parser/IqParser.java b/src/eu/siacs/conversations/parser/IqParser.java
new file mode 100644
index 00000000..acbeee4d
--- /dev/null
+++ b/src/eu/siacs/conversations/parser/IqParser.java
@@ -0,0 +1,89 @@
+package eu.siacs.conversations.parser;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.OnIqPacketReceived;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+public class IqParser extends AbstractParser implements OnIqPacketReceived {
+
+ public IqParser(XmppConnectionService service) {
+ super(service);
+ }
+
+ public void rosterItems(Account account, Element query) {
+ String version = query.getAttribute("ver");
+ if (version != null) {
+ account.getRoster().setVersion(version);
+ }
+ for (Element item : query.getChildren()) {
+ if (item.getName().equals("item")) {
+ String jid = item.getAttribute("jid");
+ String name = item.getAttribute("name");
+ String subscription = item.getAttribute("subscription");
+ Contact contact = account.getRoster().getContact(jid);
+ if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
+ contact.setServerName(name);
+ }
+ if (subscription.equals("remove")) {
+ contact.resetOption(Contact.Options.IN_ROSTER);
+ contact.resetOption(Contact.Options.DIRTY_DELETE);
+ contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
+ } else {
+ contact.setOption(Contact.Options.IN_ROSTER);
+ contact.resetOption(Contact.Options.DIRTY_PUSH);
+ contact.parseSubscriptionFromElement(item);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ if (packet.hasChild("query", "jabber:iq:roster")) {
+ String from = packet.getFrom();
+ if ((from == null) || (from.equals(account.getJid()))) {
+ Element query = packet.findChild("query");
+ this.rosterItems(account, query);
+ }
+ } else if (packet
+ .hasChild("open", "http://jabber.org/protocol/ibb")
+ || packet
+ .hasChild("data", "http://jabber.org/protocol/ibb")) {
+ mXmppConnectionService.getJingleConnectionManager().deliverIbbPacket(account, packet);
+ } else if (packet.hasChild("query",
+ "http://jabber.org/protocol/disco#info")) {
+ IqPacket iqResponse = packet
+ .generateRespone(IqPacket.TYPE_RESULT);
+ Element query = iqResponse.addChild("query",
+ "http://jabber.org/protocol/disco#info");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:1");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:apps:file-transfer:3");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:transports:s5b:1");
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:jingle:transports:ibb:1");
+ if (mXmppConnectionService.confirmMessages()) {
+ query.addChild("feature").setAttribute("var",
+ "urn:xmpp:receipts");
+ }
+ account.getXmppConnection().sendIqPacket(iqResponse, null);
+ } else {
+ if ((packet.getType() == IqPacket.TYPE_GET)
+ || (packet.getType() == IqPacket.TYPE_SET)) {
+ IqPacket response = packet
+ .generateRespone(IqPacket.TYPE_ERROR);
+ Element error = response.addChild("error");
+ error.setAttribute("type", "cancel");
+ error.addChild("feature-not-implemented",
+ "urn:ietf:params:xml:ns:xmpp-stanzas");
+ account.getXmppConnection().sendIqPacket(response, null);
+ }
+ }
+ }
+
+}
diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java
index 598cf830..1673fbf0 100644
--- a/src/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/eu/siacs/conversations/parser/MessageParser.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.parser;
+import android.os.SystemClock;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.entities.Account;
@@ -8,25 +9,29 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
-public class MessageParser extends AbstractParser {
+public class MessageParser extends AbstractParser implements
+ OnMessagePacketReceived {
+
+ private long lastCarbonMessageReceived = -XmppConnectionService.CARBON_GRACE_PERIOD;
public MessageParser(XmppConnectionService service) {
super(service);
}
- public Message parseChat(MessagePacket packet, Account account) {
+ private Message parseChat(MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/");
Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], false);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
- updateLastseen(packet, account,true);
+ updateLastseen(packet, account, true);
String pgpBody = getPgpBody(packet);
Message finishedMessage;
if (pgpBody != null) {
- finishedMessage = new Message(conversation, packet.getFrom(), pgpBody,
- Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
+ finishedMessage = new Message(conversation, packet.getFrom(),
+ pgpBody, Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
} else {
finishedMessage = new Message(conversation, packet.getFrom(),
packet.getBody(), Message.ENCRYPTION_NONE,
@@ -36,13 +41,13 @@ public class MessageParser extends AbstractParser {
return finishedMessage;
}
- public Message parseOtrChat(MessagePacket packet, Account account) {
+ private Message parseOtrChat(MessagePacket packet, Account account) {
boolean properlyAddressed = (packet.getTo().split("/").length == 2)
|| (account.countPresences() == 1);
String[] fromParts = packet.getFrom().split("/");
Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], false);
- updateLastseen(packet, account,true);
+ updateLastseen(packet, account, true);
String body = packet.getBody();
if (!conversation.hasValidOtrSession()) {
if (properlyAddressed) {
@@ -84,22 +89,24 @@ public class MessageParser extends AbstractParser {
conversation.setSymmetricKey(CryptoHelper.hexToBytes(key));
return null;
}
- conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
- Message finishedMessage = new Message(conversation, packet.getFrom(), body,
- Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
+ conversation
+ .setLatestMarkableMessageId(getMarkableMessageId(packet));
+ Message finishedMessage = new Message(conversation,
+ packet.getFrom(), body, Message.ENCRYPTION_OTR,
+ Message.STATUS_RECIEVED);
finishedMessage.setTime(getTimestamp(packet));
return finishedMessage;
} catch (Exception e) {
String receivedId = packet.getId();
- if (receivedId!=null) {
- mXmppConnectionService.replyWithNotAcceptable(account,packet);
+ if (receivedId != null) {
+ mXmppConnectionService.replyWithNotAcceptable(account, packet);
}
conversation.endOtrIfNeeded();
return null;
}
}
- public Message parseGroupchat(MessagePacket packet, Account account) {
+ private Message parseGroupchat(MessagePacket packet, Account account) {
int status;
String[] fromParts = packet.getFrom().split("/");
Conversation conversation = mXmppConnectionService
@@ -107,7 +114,7 @@ public class MessageParser extends AbstractParser {
if (packet.hasChild("subject")) {
conversation.getMucOptions().setSubject(
packet.findChild("subject").getContent());
- mXmppConnectionService.updateUi(conversation, false);
+ mXmppConnectionService.updateConversationUi();
return null;
}
if ((fromParts.length == 1)) {
@@ -128,17 +135,17 @@ public class MessageParser extends AbstractParser {
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
Message finishedMessage;
if (pgpBody == null) {
- finishedMessage = new Message(conversation, counterPart, packet.getBody(),
- Message.ENCRYPTION_NONE, status);
+ finishedMessage = new Message(conversation, counterPart,
+ packet.getBody(), Message.ENCRYPTION_NONE, status);
} else {
- finishedMessage= new Message(conversation, counterPart, pgpBody,
+ finishedMessage = new Message(conversation, counterPart, pgpBody,
Message.ENCRYPTION_PGP, status);
}
finishedMessage.setTime(getTimestamp(packet));
return finishedMessage;
}
- public Message parseCarbonMessage(MessagePacket packet, Account account) {
+ private Message parseCarbonMessage(MessagePacket packet, Account account) {
int status;
String fullJid;
Element forwarded;
@@ -155,11 +162,15 @@ public class MessageParser extends AbstractParser {
return null;
}
Element message = forwarded.findChild("message");
- if ((message == null) || (!message.hasChild("body")))
- return null; // either malformed or boring
+ if ((message == null) || (!message.hasChild("body"))) {
+ if (status == Message.STATUS_RECIEVED) {
+ parseNormal(message, account);
+ }
+ return null;
+ }
if (status == Message.STATUS_RECIEVED) {
fullJid = message.getAttribute("from");
- updateLastseen(message, account,true);
+ updateLastseen(message, account, true);
} else {
fullJid = message.getAttribute("to");
}
@@ -170,38 +181,46 @@ public class MessageParser extends AbstractParser {
String pgpBody = getPgpBody(message);
Message finishedMessage;
if (pgpBody != null) {
- finishedMessage = new Message(conversation, fullJid, pgpBody,Message.ENCRYPTION_PGP, status);
+ finishedMessage = new Message(conversation, fullJid, pgpBody,
+ Message.ENCRYPTION_PGP, status);
} else {
String body = message.findChild("body").getContent();
- finishedMessage= new Message(conversation, fullJid, body,Message.ENCRYPTION_NONE, status);
+ finishedMessage = new Message(conversation, fullJid, body,
+ Message.ENCRYPTION_NONE, status);
}
finishedMessage.setTime(getTimestamp(message));
return finishedMessage;
}
- public void parseError(MessagePacket packet, Account account) {
+ private void parseError(MessagePacket packet, Account account) {
String[] fromParts = packet.getFrom().split("/");
mXmppConnectionService.markMessage(account, fromParts[0],
packet.getId(), Message.STATUS_SEND_FAILED);
}
-
- public void parseNormal(MessagePacket packet, Account account) {
- if (packet.hasChild("displayed","urn:xmpp:chat-markers:0")) {
- String id = packet.findChild("displayed","urn:xmpp:chat-markers:0").getAttribute("id");
- String[] fromParts = packet.getFrom().split("/");
- updateLastseen(packet, account,true);
- mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_DISPLAYED);
- } else if (packet.hasChild("received","urn:xmpp:chat-markers:0")) {
- String id = packet.findChild("received","urn:xmpp:chat-markers:0").getAttribute("id");
- String[] fromParts = packet.getFrom().split("/");
- updateLastseen(packet, account,false);
- mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_RECEIVED);
+
+ private void parseNormal(Element packet, Account account) {
+ if (packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
+ String id = packet
+ .findChild("displayed", "urn:xmpp:chat-markers:0")
+ .getAttribute("id");
+ String[] fromParts = packet.getAttribute("from").split("/");
+ updateLastseen(packet, account, true);
+ mXmppConnectionService.markMessage(account, fromParts[0], id,
+ Message.STATUS_SEND_DISPLAYED);
+ } else if (packet.hasChild("received", "urn:xmpp:chat-markers:0")) {
+ String id = packet.findChild("received", "urn:xmpp:chat-markers:0")
+ .getAttribute("id");
+ String[] fromParts = packet.getAttribute("from").split("/");
+ updateLastseen(packet, account, false);
+ mXmppConnectionService.markMessage(account, fromParts[0], id,
+ Message.STATUS_SEND_RECEIVED);
} else if (packet.hasChild("x")) {
Element x = packet.findChild("x");
if (x.hasChild("invite")) {
- Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, packet.getFrom(),
- true);
- mXmppConnectionService.updateUi(conversation, false);
+ mXmppConnectionService
+ .findOrCreateConversation(account,
+ packet.getAttribute("from"), true);
+ mXmppConnectionService.updateConversationUi();
}
}
@@ -215,7 +234,7 @@ public class MessageParser extends AbstractParser {
return child.getContent();
}
}
-
+
private String getMarkableMessageId(Element message) {
if (message.hasChild("markable", "urn:xmpp:chat-markers:0")) {
return message.getAttribute("id");
@@ -224,5 +243,81 @@ public class MessageParser extends AbstractParser {
}
}
-
+ @Override
+ public void onMessagePacketReceived(Account account, MessagePacket packet) {
+ Message message = null;
+ boolean notify = true;
+ if (mXmppConnectionService.getPreferences().getBoolean(
+ "notification_grace_period_after_carbon_received", true)) {
+ notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > XmppConnectionService.CARBON_GRACE_PERIOD;
+ }
+
+ if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
+ if ((packet.getBody() != null)
+ && (packet.getBody().startsWith("?OTR"))) {
+ message = this.parseOtrChat(packet, account);
+ if (message != null) {
+ message.markUnread();
+ }
+ } else if (packet.hasChild("body")) {
+ message = this.parseChat(packet, account);
+ message.markUnread();
+ } else if (packet.hasChild("received") || (packet.hasChild("sent"))) {
+ message = this.parseCarbonMessage(packet, account);
+ if (message != null) {
+ if (message.getStatus() == Message.STATUS_SEND) {
+ lastCarbonMessageReceived = SystemClock
+ .elapsedRealtime();
+ notify = false;
+ message.getConversation().markRead();
+ } else {
+ message.markUnread();
+ }
+ }
+ }
+
+ } else if (packet.getType() == MessagePacket.TYPE_GROUPCHAT) {
+ message = this.parseGroupchat(packet, account);
+ if (message != null) {
+ if (message.getStatus() == Message.STATUS_RECIEVED) {
+ message.markUnread();
+ } else {
+ message.getConversation().markRead();
+ notify = false;
+ }
+ }
+ } else if (packet.getType() == MessagePacket.TYPE_ERROR) {
+ this.parseError(packet, account);
+ return;
+ } else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
+ this.parseNormal(packet, account);
+ }
+ if ((message == null) || (message.getBody() == null)) {
+ return;
+ }
+ if ((mXmppConnectionService.confirmMessages())
+ && ((packet.getId() != null))) {
+ MessagePacket receivedPacket = new MessagePacket();
+ receivedPacket.setType(MessagePacket.TYPE_NORMAL);
+ receivedPacket.setTo(message.getCounterpart());
+ receivedPacket.setFrom(account.getFullJid());
+ if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
+ Element received = receivedPacket.addChild("received",
+ "urn:xmpp:chat-markers:0");
+ received.setAttribute("id", packet.getId());
+ account.getXmppConnection().sendMessagePacket(receivedPacket);
+ } else if (packet.hasChild("request", "urn:xmpp:receipts")) {
+ Element received = receivedPacket.addChild("received",
+ "urn:xmpp:receipts");
+ received.setAttribute("id", packet.getId());
+ account.getXmppConnection().sendMessagePacket(receivedPacket);
+ }
+ }
+ Conversation conversation = message.getConversation();
+ conversation.getMessages().add(message);
+ if (packet.getType() != MessagePacket.TYPE_ERROR) {
+ mXmppConnectionService.databaseBackend.createMessage(message);
+ }
+ mXmppConnectionService.notifyUi(conversation, notify);
+ }
}
diff --git a/src/eu/siacs/conversations/parser/PresenceParser.java b/src/eu/siacs/conversations/parser/PresenceParser.java
index 8cc57bad..bd2aa636 100644
--- a/src/eu/siacs/conversations/parser/PresenceParser.java
+++ b/src/eu/siacs/conversations/parser/PresenceParser.java
@@ -5,12 +5,15 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.generator.PresenceGenerator;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
-public class PresenceParser extends AbstractParser {
-
+public class PresenceParser extends AbstractParser implements
+ OnPresencePacketReceived {
+
public PresenceParser(XmppConnectionService service) {
super(service);
}
@@ -30,14 +33,15 @@ public class PresenceParser extends AbstractParser {
int error = muc.getMucOptions().getError();
muc.getMucOptions().processPacket(packet, mPgpEngine);
if (muc.getMucOptions().getError() != error) {
- mXmppConnectionService.updateUi(muc, false);
+ mXmppConnectionService.updateConversationUi();
}
}
}
}
public void parseContactPresence(PresencePacket packet, Account account) {
- if (packet.getFrom()==null) {
+ PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator();
+ if (packet.getFrom() == null) {
return;
}
String[] fromParts = packet.getFrom().split("/");
@@ -75,9 +79,9 @@ public class PresenceParser extends AbstractParser {
}
}
boolean online = sizeBefore < contact.getPresences().size();
- updateLastseen(packet, account,true);
+ updateLastseen(packet, account, true);
mXmppConnectionService.onContactStatusChanged
- .onContactStatusChanged(contact,online);
+ .onContactStatusChanged(contact, online);
}
} else if (type.equals("unavailable")) {
if (fromParts.length != 2) {
@@ -86,17 +90,10 @@ public class PresenceParser extends AbstractParser {
contact.removePresence(fromParts[1]);
}
mXmppConnectionService.onContactStatusChanged
- .onContactStatusChanged(contact,false);
+ .onContactStatusChanged(contact, false);
} else if (type.equals("subscribe")) {
if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
- mXmppConnectionService.sendPresenceUpdatesTo(contact);
- contact.setOption(Contact.Options.FROM);
- contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
- if ((contact.getOption(Contact.Options.ASKING))
- && (!contact.getOption(Contact.Options.TO))) {
- mXmppConnectionService
- .requestPresenceUpdatesFrom(contact);
- }
+ mXmppConnectionService.sendPresencePacket(account, mPresenceGenerator.sendPresenceUpdatesTo(contact));
} else {
contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
}
@@ -104,4 +101,15 @@ public class PresenceParser extends AbstractParser {
}
}
+ @Override
+ public void onPresencePacketReceived(Account account, PresencePacket packet) {
+ if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
+ this.parseConferencePresence(packet, account);
+ } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) {
+ this.parseConferencePresence(packet, account);
+ } else {
+ this.parseContactPresence(packet, account);
+ }
+ }
+
}
diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java
index fbf45d25..7643076a 100644
--- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -116,8 +116,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
return cursor.getInt(0);
}
- public List<Conversation> getConversations(int status) {
- List<Conversation> list = new ArrayList<Conversation>();
+ public CopyOnWriteArrayList<Conversation> getConversations(int status) {
+ CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<Conversation>();
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { "" + status };
Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index 3db52753..c43a34b7 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -2,6 +2,7 @@ package eu.siacs.conversations.services;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@@ -9,6 +10,7 @@ import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
@@ -18,6 +20,7 @@ import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
@@ -25,12 +28,12 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.generator.MessageGenerator;
+import eu.siacs.conversations.generator.PresenceGenerator;
+import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.parser.MessageParser;
import eu.siacs.conversations.parser.PresenceParser;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.ui.OnAccountListChangedListener;
-import eu.siacs.conversations.ui.OnConversationListChangedListener;
import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.ExceptionHelper;
@@ -42,8 +45,6 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnBindListener;
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
-import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
-import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.OnStatusChanged;
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
import eu.siacs.conversations.xmpp.XmppConnection;
@@ -86,22 +87,24 @@ public class XmppConnectionService extends Service {
private static final int PING_MIN_INTERVAL = 30;
private static final int PING_TIMEOUT = 10;
private static final int CONNECT_TIMEOUT = 90;
- private static final long CARBON_GRACE_PERIOD = 60000L;
+ public static final long CARBON_GRACE_PERIOD = 60000L;
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private MessageParser mMessageParser = new MessageParser(this);
private PresenceParser mPresenceParser = new PresenceParser(this);
+ private IqParser mIqParser = new IqParser(this);
private MessageGenerator mMessageGenerator = new MessageGenerator();
-
+ private PresenceGenerator mPresenceGenerator = new PresenceGenerator();
+
private List<Account> accounts;
- private List<Conversation> conversations = null;
+ private CopyOnWriteArrayList<Conversation> conversations = null;
private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
this);
- private OnConversationListChangedListener convChangedListener = null;
+ private OnConversationUpdate mOnConversationUpdate = null;
private int convChangedListenerCount = 0;
- private OnAccountListChangedListener accountChangedListener = null;
+ private OnAccountUpdate mOnAccountUpdate = null;
private OnTLSExceptionReceived tlsException = null;
public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
@@ -124,8 +127,6 @@ public class XmppConnectionService extends Service {
private SecureRandom mRandom;
- private long lastCarbonMessageReceived = -CARBON_GRACE_PERIOD;
-
private ContentObserver contactObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
@@ -138,101 +139,12 @@ public class XmppConnectionService extends Service {
};
private final IBinder mBinder = new XmppConnectionBinder();
- private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
-
- @Override
- public void onMessagePacketReceived(Account account,
- MessagePacket packet) {
- Message message = null;
- boolean notify = true;
- if (getPreferences().getBoolean(
- "notification_grace_period_after_carbon_received", true)) {
- notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > CARBON_GRACE_PERIOD;
- }
-
- if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
- if ((packet.getBody() != null)
- && (packet.getBody().startsWith("?OTR"))) {
- message = mMessageParser.parseOtrChat(packet, account);
- if (message != null) {
- message.markUnread();
- }
- } else if (packet.hasChild("body")) {
- message = mMessageParser.parseChat(packet, account);
- message.markUnread();
- } else if (packet.hasChild("received")
- || (packet.hasChild("sent"))) {
- message = mMessageParser
- .parseCarbonMessage(packet, account);
- if (message != null) {
- if (message.getStatus() == Message.STATUS_SEND) {
- lastCarbonMessageReceived = SystemClock
- .elapsedRealtime();
- notify = false;
- message.getConversation().markRead();
- } else {
- message.markUnread();
- }
- }
- }
-
- } else if (packet.getType() == MessagePacket.TYPE_GROUPCHAT) {
- message = mMessageParser.parseGroupchat(packet, account);
- if (message != null) {
- if (message.getStatus() == Message.STATUS_RECIEVED) {
- message.markUnread();
- } else {
- message.getConversation().markRead();
- notify = false;
- }
- }
- } else if (packet.getType() == MessagePacket.TYPE_ERROR) {
- mMessageParser.parseError(packet, account);
- return;
- } else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
- mMessageParser.parseNormal(packet, account);
- }
- if ((message == null) || (message.getBody() == null)) {
- return;
- }
- if ((confirmMessages()) && ((packet.getId() != null))) {
- MessagePacket receivedPacket = new MessagePacket();
- receivedPacket.setType(MessagePacket.TYPE_NORMAL);
- receivedPacket.setTo(message.getCounterpart());
- receivedPacket.setFrom(account.getFullJid());
- if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
- Element received = receivedPacket.addChild("received",
- "urn:xmpp:chat-markers:0");
- received.setAttribute("id", packet.getId());
- account.getXmppConnection().sendMessagePacket(
- receivedPacket);
- } else if (packet.hasChild("request", "urn:xmpp:receipts")) {
- Element received = receivedPacket.addChild("received",
- "urn:xmpp:receipts");
- received.setAttribute("id", packet.getId());
- account.getXmppConnection().sendMessagePacket(
- receivedPacket);
- }
- }
- Conversation conversation = message.getConversation();
- conversation.getMessages().add(message);
- if (packet.getType() != MessagePacket.TYPE_ERROR) {
- databaseBackend.createMessage(message);
- }
- if (convChangedListener != null) {
- convChangedListener.onConversationListChanged();
- } else {
- UIHelper.updateNotification(getApplicationContext(),
- getConversations(), message.getConversation(), notify);
- }
- }
- };
private OnStatusChanged statusListener = new OnStatusChanged() {
@Override
public void onStatusChanged(Account account) {
- if (accountChangedListener != null) {
- accountChangedListener.onAccountListChangedListener();
+ if (mOnAccountUpdate != null) {
+ mOnAccountUpdate.onAccountUpdate();;
}
if (account.getStatus() == Account.STATUS_ONLINE) {
mJingleConnectionManager.cancelInTransmission();
@@ -269,73 +181,6 @@ public class XmppConnectionService extends Service {
}
};
- private OnPresencePacketReceived presenceListener = new OnPresencePacketReceived() {
-
- @Override
- public void onPresencePacketReceived(final Account account,
- PresencePacket packet) {
- if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
- mPresenceParser.parseConferencePresence(packet, account);
- } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) {
- mPresenceParser.parseConferencePresence(packet, account);
- } else {
- mPresenceParser.parseContactPresence(packet, account);
- }
- }
- };
-
- private OnIqPacketReceived unknownIqListener = new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.hasChild("query", "jabber:iq:roster")) {
- String from = packet.getFrom();
- if ((from == null) || (from.equals(account.getJid()))) {
- Element query = packet.findChild("query");
- processRosterItems(account, query);
- } else {
- Log.d(LOGTAG, "unauthorized roster push from: " + from);
- }
- } else if (packet
- .hasChild("open", "http://jabber.org/protocol/ibb")
- || packet
- .hasChild("data", "http://jabber.org/protocol/ibb")) {
- XmppConnectionService.this.mJingleConnectionManager
- .deliverIbbPacket(account, packet);
- } else if (packet.hasChild("query",
- "http://jabber.org/protocol/disco#info")) {
- IqPacket iqResponse = packet
- .generateRespone(IqPacket.TYPE_RESULT);
- Element query = iqResponse.addChild("query",
- "http://jabber.org/protocol/disco#info");
- query.addChild("feature").setAttribute("var",
- "urn:xmpp:jingle:1");
- query.addChild("feature").setAttribute("var",
- "urn:xmpp:jingle:apps:file-transfer:3");
- query.addChild("feature").setAttribute("var",
- "urn:xmpp:jingle:transports:s5b:1");
- query.addChild("feature").setAttribute("var",
- "urn:xmpp:jingle:transports:ibb:1");
- if (confirmMessages()) {
- query.addChild("feature").setAttribute("var",
- "urn:xmpp:receipts");
- }
- account.getXmppConnection().sendIqPacket(iqResponse, null);
- } else {
- if ((packet.getType() == IqPacket.TYPE_GET)
- || (packet.getType() == IqPacket.TYPE_SET)) {
- IqPacket response = packet
- .generateRespone(IqPacket.TYPE_ERROR);
- Element error = response.addChild("error");
- error.setAttribute("type", "cancel");
- error.addChild("feature-not-implemented",
- "urn:ietf:params:xml:ns:xmpp-stanzas");
- account.getXmppConnection().sendIqPacket(response, null);
- }
- }
- }
- };
-
private OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
@Override
@@ -401,9 +246,13 @@ public class XmppConnectionService extends Service {
return message;
}
- public Conversation findMuc(String name, Account account) {
+ public Conversation findMuc(Bookmark bookmark) {
+ return findMuc(bookmark.getJid(), bookmark.getAccount());
+ }
+
+ public Conversation findMuc(String jid, Account account) {
for (Conversation conversation : this.conversations) {
- if (conversation.getContactJid().split("/")[0].equals(name)
+ if (conversation.getContactJid().split("/")[0].equals(jid)
&& (conversation.getAccount() == account)) {
return conversation;
}
@@ -411,31 +260,6 @@ public class XmppConnectionService extends Service {
return null;
}
- private void processRosterItems(Account account, Element elements) {
- String version = elements.getAttribute("ver");
- if (version != null) {
- account.getRoster().setVersion(version);
- }
- for (Element item : elements.getChildren()) {
- if (item.getName().equals("item")) {
- String jid = item.getAttribute("jid");
- String name = item.getAttribute("name");
- String subscription = item.getAttribute("subscription");
- Contact contact = account.getRoster().getContact(jid);
- if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
- contact.setServerName(name);
- }
- if (subscription.equals("remove")) {
- contact.resetOption(Contact.Options.IN_ROSTER);
- contact.resetOption(Contact.Options.DIRTY_DELETE);
- } else {
- contact.setOption(Contact.Options.IN_ROSTER);
- contact.parseSubscriptionFromElement(item);
- }
- }
- }
- }
-
public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() {
return XmppConnectionService.this;
@@ -508,13 +332,16 @@ public class XmppConnectionService extends Service {
// in any case. reschedule wakup call
this.scheduleWakeupCall(PING_MAX_INTERVAL, true);
}
- if (accountChangedListener != null) {
- accountChangedListener.onAccountListChangedListener();
+ if (mOnAccountUpdate != null) {
+ mOnAccountUpdate.onAccountUpdate();
}
}
}
if (wakeLock.isHeld()) {
- try { wakeLock.release();} catch (RuntimeException re) {}
+ try {
+ wakeLock.release();
+ } catch (RuntimeException re) {
+ }
}
return START_STICKY;
}
@@ -618,11 +445,11 @@ public class XmppConnectionService extends Service {
account.setResource(sharedPref.getString("resource", "mobile")
.toLowerCase(Locale.getDefault()));
XmppConnection connection = new XmppConnection(account, this);
- connection.setOnMessagePacketReceivedListener(this.messageListener);
+ connection.setOnMessagePacketReceivedListener(this.mMessageParser);
connection.setOnStatusChangedListener(this.statusListener);
- connection.setOnPresencePacketReceivedListener(this.presenceListener);
+ connection.setOnPresencePacketReceivedListener(this.mPresenceParser);
connection
- .setOnUnregisteredIqPacketReceivedListener(this.unknownIqListener);
+ .setOnUnregisteredIqPacketReceivedListener(this.mIqParser);
connection.setOnJinglePacketReceivedListener(this.jingleListener);
connection
.setOnTLSExceptionReceivedListener(new OnTLSExceptionReceived() {
@@ -644,11 +471,10 @@ public class XmppConnectionService extends Service {
account.getRoster().clearPresences();
account.clearPresences(); // self presences
fetchRosterFromServer(account);
- sendPresence(account);
+ fetchBookmarks(account);
+ sendPresencePacket(account, mPresenceGenerator.sendPresence(account));
connectMultiModeConversations(account);
- if (convChangedListener != null) {
- convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
}
});
return connection;
@@ -691,15 +517,12 @@ public class XmppConnectionService extends Service {
message.setStatus(Message.STATUS_WAITING);
} else if (conv.hasValidOtrSession()
&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
- message.setPresence(conv.getOtrSession().getSessionID().getUserID());
- try {
- packet = mMessageGenerator.generateOtrChat(message);
- send = true;
- message.setStatus(Message.STATUS_SEND);
- } catch (OtrException e) {
- Log.e(LOGTAG,"error generating otr packet");
- packet = null;
- }
+ message.setPresence(conv.getOtrSession().getSessionID()
+ .getUserID());
+ packet = mMessageGenerator.generateOtrChat(message);
+ send = true;
+ message.setStatus(Message.STATUS_SEND);
+
} else if (message.getPresence() == null) {
message.setStatus(Message.STATUS_WAITING);
}
@@ -744,11 +567,9 @@ public class XmppConnectionService extends Service {
databaseBackend.createMessage(message);
}
conv.getMessages().add(message);
- if (convChangedListener != null) {
- convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
if ((send) && (packet != null)) {
- account.getXmppConnection().sendMessagePacket(packet);
+ sendMessagePacket(account, packet);
}
}
@@ -782,9 +603,11 @@ public class XmppConnectionService extends Service {
}
}
} else {
- if (message.getConversation().getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
+ if (message.getConversation().getOtrSession()
+ .getSessionStatus() == SessionStatus.ENCRYPTED) {
if (message.getType() == Message.TYPE_TEXT) {
- packet = mMessageGenerator.generateOtrChat(message,true);
+ packet = mMessageGenerator.generateOtrChat(message,
+ true);
} else if (message.getType() == Message.TYPE_IMAGE) {
mJingleConnectionManager.createNewConnection(message);
}
@@ -792,9 +615,10 @@ public class XmppConnectionService extends Service {
}
} else if (message.getType() == Message.TYPE_TEXT) {
if (message.getEncryption() == Message.ENCRYPTION_NONE) {
- packet = mMessageGenerator.generateChat(message,true);
- } else if ((message.getEncryption() == Message.ENCRYPTION_DECRYPTED)||(message.getEncryption() == Message.ENCRYPTION_PGP)) {
- packet = mMessageGenerator.generatePgpChat(message,true);
+ packet = mMessageGenerator.generateChat(message, true);
+ } else if ((message.getEncryption() == Message.ENCRYPTION_DECRYPTED)
+ || (message.getEncryption() == Message.ENCRYPTION_PGP)) {
+ packet = mMessageGenerator.generatePgpChat(message, true);
}
} else if (message.getType() == Message.TYPE_IMAGE) {
Presences presences = message.getConversation().getContact()
@@ -813,7 +637,7 @@ public class XmppConnectionService extends Service {
}
}
if (packet != null) {
- account.getXmppConnection().sendMessagePacket(packet);
+ sendMessagePacket(account,packet);
markMessage(message, Message.STATUS_SEND);
}
}
@@ -834,14 +658,60 @@ public class XmppConnectionService extends Service {
@Override
public void onIqPacketReceived(final Account account,
IqPacket packet) {
- Element roster = packet.findChild("query");
- if (roster != null) {
+ Element query = packet.findChild("query");
+ if (query != null) {
account.getRoster().markAllAsNotInRoster();
- processRosterItems(account, roster);
+ mIqParser.rosterItems(account, query);
}
}
});
}
+
+ public void fetchBookmarks(Account account) {
+ IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
+ Element query = iqPacket.query("jabber:iq:private");
+ query.addChild("storage", "storage:bookmarks");
+ OnIqPacketReceived callback = new OnIqPacketReceived() {
+
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Element query = packet.query();
+ List<Bookmark> bookmarks = new ArrayList<Bookmark>();
+ Element storage = query.findChild("storage", "storage:bookmarks");
+ if (storage!=null) {
+ for(Element item : storage.getChildren()) {
+ if (item.getName().equals("conference")) {
+ Log.d(LOGTAG,item.toString());
+ Bookmark bookmark = Bookmark.parse(item,account);
+ bookmarks.add(bookmark);
+ Conversation conversation = findMuc(bookmark);
+ if (conversation!=null) {
+ conversation.setBookmark(bookmark);
+ } else {
+ if (bookmark.autojoin()) {
+ conversation = findOrCreateConversation(account, bookmark.getJid(), true);
+ conversation.setBookmark(bookmark);
+ }
+ }
+ }
+ }
+ }
+ account.setBookmarks(bookmarks);
+ }
+ };
+ sendIqPacket(account, iqPacket, callback);
+
+ }
+
+ public void pushBookmarks(Account account) {
+ IqPacket iqPacket = new IqPacket(IqPacket.TYPE_SET);
+ Element query = iqPacket.query("jabber:iq:private");
+ Element storage = query.addChild("storage", "storage:bookmarks");
+ for(Bookmark bookmark : account.getBookmarks()) {
+ storage.addChild(bookmark.toElement());
+ }
+ sendIqPacket(account, iqPacket,null);
+ }
private void mergePhoneContactsWithRoster() {
PhoneHelper.loadPhoneContacts(getApplicationContext(),
@@ -885,7 +755,14 @@ public class XmppConnectionService extends Service {
conv.setMessages(databaseBackend.getMessages(conv, 50));
}
}
- Collections.sort(this.conversations, new Comparator<Conversation>() {
+
+ return this.conversations;
+ }
+
+ public void populateWithOrderedConversations(List<Conversation> list) {
+ list.clear();
+ list.addAll(getConversations());
+ Collections.sort(list, new Comparator<Conversation>() {
@Override
public int compare(Conversation lhs, Conversation rhs) {
Message left = lhs.getLatestMessage();
@@ -899,7 +776,6 @@ public class XmppConnectionService extends Service {
}
}
});
- return this.conversations;
}
public List<Message> getMoreMessages(Conversation conversation,
@@ -968,32 +844,31 @@ public class XmppConnectionService extends Service {
&& (conversation.getMode() == Conversation.MODE_MULTI)) {
joinMuc(conversation);
}
- if (this.convChangedListener != null) {
- this.convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
return conversation;
}
public void archiveConversation(Conversation conversation) {
if (conversation.getMode() == Conversation.MODE_MULTI) {
+ Bookmark bookmark = conversation.getBookmark();
+ if (bookmark!=null && bookmark.autojoin()) {
+ bookmark.setAutojoin(false);
+ pushBookmarks(bookmark.getAccount());
+ }
leaveMuc(conversation);
} else {
conversation.endOtrIfNeeded();
}
this.databaseBackend.updateConversation(conversation);
this.conversations.remove(conversation);
- if (this.convChangedListener != null) {
- this.convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
}
public void clearConversationHistory(Conversation conversation) {
this.databaseBackend.deleteMessagesInConversation(conversation);
this.fileBackend.removeFiles(conversation);
conversation.getMessages().clear();
- if (this.convChangedListener != null) {
- this.convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
}
public int getConversationCount() {
@@ -1004,17 +879,14 @@ public class XmppConnectionService extends Service {
databaseBackend.createAccount(account);
this.accounts.add(account);
this.reconnectAccount(account, false);
- if (accountChangedListener != null)
- accountChangedListener.onAccountListChangedListener();
+ updateAccountUi();
}
public void updateAccount(Account account) {
this.statusListener.onStatusChanged(account);
databaseBackend.updateAccount(account);
reconnectAccount(account, false);
- if (accountChangedListener != null) {
- accountChangedListener.onAccountListChangedListener();
- }
+ updateAccountUi();
UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
}
@@ -1024,32 +896,29 @@ public class XmppConnectionService extends Service {
}
databaseBackend.deleteAccount(account);
this.accounts.remove(account);
- if (accountChangedListener != null) {
- accountChangedListener.onAccountListChangedListener();
- }
+ updateAccountUi();
UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
}
public void setOnConversationListChangedListener(
- OnConversationListChangedListener listener) {
- this.convChangedListener = listener;
+ OnConversationUpdate listener) {
+ this.mOnConversationUpdate = listener;
this.convChangedListenerCount++;
}
public void removeOnConversationListChangedListener() {
this.convChangedListenerCount--;
if (this.convChangedListenerCount == 0) {
- this.convChangedListener = null;
+ this.mOnConversationUpdate = null;
}
}
- public void setOnAccountListChangedListener(
- OnAccountListChangedListener listener) {
- this.accountChangedListener = listener;
+ public void setOnAccountListChangedListener(OnAccountUpdate listener) {
+ this.mOnAccountUpdate = listener;
}
public void removeOnAccountListChangedListener() {
- this.accountChangedListener = null;
+ this.mOnAccountUpdate = null;
}
public void connectMultiModeConversations(Account account) {
@@ -1085,13 +954,16 @@ public class XmppConnectionService extends Service {
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
if (conversation.getMessages().size() != 0) {
- final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",Locale.US);
+ final SimpleDateFormat mDateFormat = new SimpleDateFormat(
+ "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date date = new Date(conversation.getLatestMessage().getTimeSent() + 1000);
- x.addChild("history").setAttribute("since",mDateFormat.format(date));
+ Date date = new Date(
+ conversation.getLatestMessage().getTimeSent() + 1000);
+ x.addChild("history").setAttribute("since",
+ mDateFormat.format(date));
}
packet.addChild(x);
- account.getXmppConnection().sendPresencePacket(packet);
+ sendPresencePacket(account, packet);
}
private OnRenameListener renameListener = null;
@@ -1130,8 +1002,7 @@ public class XmppConnectionService extends Service {
packet.addChild("status").setContent("online");
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
-
- account.getXmppConnection().sendPresencePacket(packet, null);
+ sendPresencePacket(account,packet);
} else {
String jid = conversation.getContactJid().split("/")[0] + "/"
+ nick;
@@ -1149,10 +1020,10 @@ public class XmppConnectionService extends Service {
+ "/" + conversation.getMucOptions().getNick());
packet.setAttribute("from", conversation.getAccount().getFullJid());
packet.setAttribute("type", "unavailable");
- Log.d(LOGTAG, "send leaving muc " + packet);
- conversation.getAccount().getXmppConnection()
- .sendPresencePacket(packet);
+ sendPresencePacket(conversation.getAccount(),packet);
conversation.getMucOptions().setOffline();
+ conversation.deregisterWithBookmark();
+ Log.d(LOGTAG,conversation.getAccount().getJid()+" leaving muc "+conversation.getContactJid());
}
public void disconnect(Account account, boolean force) {
@@ -1219,18 +1090,19 @@ public class XmppConnectionService extends Service {
&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
msg.setPresence(otrSession.getSessionID().getUserID());
if (msg.getType() == Message.TYPE_TEXT) {
- MessagePacket outPacket = mMessageGenerator.generateOtrChat(msg,true);
- if (outPacket!=null) {
+ MessagePacket outPacket = mMessageGenerator
+ .generateOtrChat(msg, true);
+ if (outPacket != null) {
msg.setStatus(Message.STATUS_SEND);
databaseBackend.updateMessage(msg);
- account.getXmppConnection().sendMessagePacket(outPacket);
+ sendMessagePacket(account,outPacket);
}
} else if (msg.getType() == Message.TYPE_IMAGE) {
mJingleConnectionManager.createNewConnection(msg);
}
}
}
- updateUi(conversation, false);
+ notifyUi(conversation, false);
}
public boolean renewSymmetricKey(Conversation conversation) {
@@ -1250,7 +1122,7 @@ public class XmppConnectionService extends Service {
packet.setBody(otrSession
.transformSending(CryptoHelper.FILETRANSFER
+ CryptoHelper.bytesToHex(symmetricKey)));
- account.getXmppConnection().sendMessagePacket(packet);
+ sendMessagePacket(account,packet);
conversation.setSymmetricKey(symmetricKey);
return true;
} catch (OtrException e) {
@@ -1262,26 +1134,28 @@ public class XmppConnectionService extends Service {
public void pushContactToServer(Contact contact) {
contact.resetOption(Contact.Options.DIRTY_DELETE);
+ contact.setOption(Contact.Options.DIRTY_PUSH);
Account account = contact.getAccount();
if (account.getStatus() == Account.STATUS_ONLINE) {
+ boolean ask = contact.getOption(Contact.Options.ASKING);
+ boolean sendUpdates = contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)
+ && contact.getOption(Contact.Options.PREEMPTIVE_GRANT);
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
iq.query("jabber:iq:roster").addChild(contact.asElement());
account.getXmppConnection().sendIqPacket(iq, null);
- if (contact.getOption(Contact.Options.ASKING)) {
- requestPresenceUpdatesFrom(contact);
+ if (sendUpdates) {
+ sendPresencePacket(account, mPresenceGenerator.sendPresenceUpdatesTo(contact));
}
- if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
- Log.d("xmppService", "contact had pending subscription");
- sendPresenceUpdatesTo(contact);
+ if (ask) {
+ sendPresencePacket(account, mPresenceGenerator.requestPresenceUpdatesFrom(contact));
}
- contact.resetOption(Contact.Options.DIRTY_PUSH);
- } else {
- contact.setOption(Contact.Options.DIRTY_PUSH);
}
}
public void deleteContactOnServer(Contact contact) {
+ contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
contact.resetOption(Contact.Options.DIRTY_PUSH);
+ contact.setOption(Contact.Options.DIRTY_DELETE);
Account account = contact.getAccount();
if (account.getStatus() == Account.STATUS_ONLINE) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
@@ -1289,53 +1163,7 @@ public class XmppConnectionService extends Service {
item.setAttribute("jid", contact.getJid());
item.setAttribute("subscription", "remove");
account.getXmppConnection().sendIqPacket(iq, null);
- contact.resetOption(Contact.Options.DIRTY_DELETE);
- } else {
- contact.setOption(Contact.Options.DIRTY_DELETE);
- }
- }
-
- public void requestPresenceUpdatesFrom(Contact contact) {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("type", "subscribe");
- packet.setAttribute("to", contact.getJid());
- packet.setAttribute("from", contact.getAccount().getJid());
- contact.getAccount().getXmppConnection().sendPresencePacket(packet);
- }
-
- public void stopPresenceUpdatesFrom(Contact contact) {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("type", "unsubscribe");
- packet.setAttribute("to", contact.getJid());
- packet.setAttribute("from", contact.getAccount().getJid());
- contact.getAccount().getXmppConnection().sendPresencePacket(packet);
- }
-
- public void stopPresenceUpdatesTo(Contact contact) {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("type", "unsubscribed");
- packet.setAttribute("to", contact.getJid());
- packet.setAttribute("from", contact.getAccount().getJid());
- contact.getAccount().getXmppConnection().sendPresencePacket(packet);
- }
-
- public void sendPresenceUpdatesTo(Contact contact) {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("type", "subscribed");
- packet.setAttribute("to", contact.getJid());
- packet.setAttribute("from", contact.getAccount().getJid());
- contact.getAccount().getXmppConnection().sendPresencePacket(packet);
- }
-
- public void sendPresence(Account account) {
- PresencePacket packet = new PresencePacket();
- packet.setAttribute("from", account.getFullJid());
- String sig = account.getPgpSignature();
- if (sig != null) {
- packet.addChild("status").setContent("online");
- packet.addChild("x", "jabber:x:signed").setContent(sig);
}
- account.getXmppConnection().sendPresencePacket(packet);
}
public void updateConversation(Conversation conversation) {
@@ -1366,21 +1194,6 @@ public class XmppConnectionService extends Service {
}).start();
}
- public void sendConversationSubject(Conversation conversation,
- String subject) {
- MessagePacket packet = new MessagePacket();
- packet.setType(MessagePacket.TYPE_GROUPCHAT);
- packet.setTo(conversation.getContactJid().split("/")[0]);
- Element subjectChild = new Element("subject");
- subjectChild.setContent(subject);
- packet.addChild(subjectChild);
- packet.setFrom(conversation.getAccount().getJid());
- Account account = conversation.getAccount();
- if (account.getStatus() == Account.STATUS_ONLINE) {
- account.getXmppConnection().sendMessagePacket(packet);
- }
- }
-
public void inviteToConference(Conversation conversation,
List<Contact> contacts) {
for (Contact contact : contacts) {
@@ -1394,8 +1207,7 @@ public class XmppConnectionService extends Service {
x.addChild(invite);
packet.addChild(x);
Log.d(LOGTAG, packet.toString());
- conversation.getAccount().getXmppConnection()
- .sendMessagePacket(packet);
+ sendMessagePacket(conversation.getAccount(),packet);
}
}
@@ -1425,9 +1237,7 @@ public class XmppConnectionService extends Service {
public void markMessage(Message message, int status) {
message.setStatus(status);
databaseBackend.updateMessage(message);
- if (convChangedListener != null) {
- convChangedListener.onConversationListChanged();
- }
+ updateConversationUi();
}
public SharedPreferences getPreferences() {
@@ -1439,14 +1249,26 @@ public class XmppConnectionService extends Service {
return getPreferences().getBoolean("confirm_messages", true);
}
- public void updateUi(Conversation conversation, boolean notify) {
- if (convChangedListener != null) {
- convChangedListener.onConversationListChanged();
+ public void notifyUi(Conversation conversation, boolean notify) {
+ if (mOnConversationUpdate != null) {
+ mOnConversationUpdate.onConversationUpdate();
} else {
UIHelper.updateNotification(getApplicationContext(),
getConversations(), conversation, notify);
}
}
+
+ public void updateConversationUi() {
+ if (mOnConversationUpdate != null) {
+ mOnConversationUpdate.onConversationUpdate();
+ }
+ }
+
+ public void updateAccountUi() {
+ if (mOnAccountUpdate != null) {
+ mOnAccountUpdate.onAccountUpdate();
+ }
+ }
public Account findAccountByJid(String accountJid) {
for (Account account : this.accounts) {
@@ -1458,18 +1280,13 @@ public class XmppConnectionService extends Service {
}
public void markRead(Conversation conversation) {
- conversation.markRead(this);
- }
-
- public void sendConfirmMessage(Account account, String to, String id) {
- MessagePacket receivedPacket = new MessagePacket();
- receivedPacket.setType(MessagePacket.TYPE_NORMAL);
- receivedPacket.setTo(to);
- receivedPacket.setFrom(account.getFullJid());
- Element received = receivedPacket.addChild("displayed",
- "urn:xmpp:chat-markers:0");
- received.setAttribute("id", id);
- account.getXmppConnection().sendMessagePacket(receivedPacket);
+ conversation.markRead();
+ String id = conversation.popLatestMarkableMessageId();
+ if (confirmMessages() && id != null) {
+ Account account = conversation.getAccount();
+ String to = conversation.getContactJid();
+ this.sendMessagePacket(conversation.getAccount(), mMessageGenerator.confirm(account, to, id));
+ }
}
public SecureRandom getRNG() {
@@ -1482,19 +1299,87 @@ public class XmppConnectionService extends Service {
public void replyWithNotAcceptable(Account account, MessagePacket packet) {
if (account.getStatus() == Account.STATUS_ONLINE) {
- MessagePacket error = this.mMessageGenerator.generateNotAcceptable(packet);
- account.getXmppConnection().sendMessagePacket(error);
+ MessagePacket error = this.mMessageGenerator
+ .generateNotAcceptable(packet);
+ sendMessagePacket(account,error);
}
}
-
+
public void syncRosterToDisk(final Account account) {
new Thread(new Runnable() {
-
+
@Override
public void run() {
databaseBackend.writeRoster(account.getRoster());
}
}).start();
-
+
+ }
+
+ public List<String> getKnownHosts() {
+ List<String> hosts = new ArrayList<String>();
+ for (Account account : getAccounts()) {
+ if (!hosts.contains(account.getServer())) {
+ hosts.add(account.getServer());
+ }
+ for (Contact contact : account.getRoster().getContacts()) {
+ if (contact.showInRoster()) {
+ String server = contact.getServer();
+ if (server != null && !hosts.contains(server)) {
+ hosts.add(server);
+ }
+ }
+ }
+ }
+ return hosts;
+ }
+
+ public List<String> getKnownConferenceHosts() {
+ ArrayList<String> mucServers = new ArrayList<String>();
+ for (Account account : accounts) {
+ if (account.getXmppConnection() != null) {
+ String server = account.getXmppConnection().getMucServer();
+ if (server != null) {
+ mucServers.add(server);
+ }
+ }
+ }
+ return mucServers;
+ }
+
+ public void sendMessagePacket(Account account, MessagePacket packet) {
+ account.getXmppConnection().sendMessagePacket(packet);
+ }
+
+ public void sendPresencePacket(Account account, PresencePacket packet) {
+ account.getXmppConnection().sendPresencePacket(packet);
+ }
+
+ public void sendIqPacket(Account account, IqPacket packet, OnIqPacketReceived callback) {
+ account.getXmppConnection().sendIqPacket(packet, callback);
+ }
+
+ public MessageGenerator getMessageGenerator() {
+ return this.mMessageGenerator;
+ }
+
+ public PresenceGenerator getPresenceGenerator() {
+ return this.mPresenceGenerator;
+ }
+
+ public JingleConnectionManager getJingleConnectionManager() {
+ return this.mJingleConnectionManager;
+ }
+
+ public interface OnConversationUpdate {
+ public void onConversationUpdate();
+ }
+
+ public interface OnAccountUpdate {
+ public void onAccountUpdate();
+ }
+
+ public interface OnRosterUpdate {
+ public void onRosterUpdate();
}
}
diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
index bee93713..9321f229 100644
--- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -31,7 +31,9 @@ import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
public class ContactDetailsActivity extends XmppActivity {
public static final String ACTION_VIEW_CONTACT = "view_contact";
@@ -47,7 +49,6 @@ public class ContactDetailsActivity extends XmppActivity {
private TextView contactJidTv;
private TextView accountJidTv;
private TextView status;
- private TextView askAgain;
private TextView lastseen;
private CheckBox send;
private CheckBox receive;
@@ -115,7 +116,6 @@ public class ContactDetailsActivity extends XmppActivity {
lastseen = (TextView) findViewById(R.id.details_lastseen);
send = (CheckBox) findViewById(R.id.details_send_presence);
receive = (CheckBox) findViewById(R.id.details_receive_presence);
- askAgain = (TextView) findViewById(R.id.ask_again);
badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
keys = (LinearLayout) findViewById(R.id.details_contact_keys);
getActionBar().setHomeButtonEnabled(true);
@@ -174,6 +174,8 @@ public class ContactDetailsActivity extends XmppActivity {
setTitle(contact.getDisplayName());
if (contact.getOption(Contact.Options.FROM)) {
send.setChecked(true);
+ } else if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)){
+ send.setChecked(false);
} else {
send.setText(R.string.preemptively_grant);
if (contact
@@ -187,17 +189,6 @@ public class ContactDetailsActivity extends XmppActivity {
receive.setChecked(true);
} else {
receive.setText(R.string.ask_for_presence_updates);
- askAgain.setVisibility(View.VISIBLE);
- askAgain.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Toast.makeText(getApplicationContext(), getString(R.string.asked_for_presence_updates),
- Toast.LENGTH_SHORT).show();
- xmppConnectionService.requestPresenceUpdatesFrom(contact);
-
- }
- });
if (contact.getOption(Contact.Options.ASKING)) {
receive.setChecked(true);
} else {
@@ -304,6 +295,8 @@ public class ContactDetailsActivity extends XmppActivity {
@Override
protected void onStop() {
super.onStop();
+ XmppConnectionService xcs = activity.xmppConnectionService;
+ PresencePacket packet = null;
boolean updated = false;
if (contact!=null) {
boolean online = contact.getAccount().getStatus() == Account.STATUS_ONLINE;
@@ -312,13 +305,12 @@ public class ContactDetailsActivity extends XmppActivity {
if (online) {
contact.resetOption(Contact.Options.FROM);
contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
- activity.xmppConnectionService.stopPresenceUpdatesTo(contact);
+ packet = xcs.getPresenceGenerator().stopPresenceUpdatesTo(contact);
}
updated = true;
}
} else {
- if (contact
- .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
+ if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
if (!send.isChecked()) {
if (online) {
contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
@@ -328,7 +320,11 @@ public class ContactDetailsActivity extends XmppActivity {
} else {
if (send.isChecked()) {
if (online) {
- contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
+ if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
+ packet = xcs.getPresenceGenerator().sendPresenceUpdatesTo(contact);
+ } else {
+ contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
+ }
}
updated = true;
}
@@ -338,7 +334,7 @@ public class ContactDetailsActivity extends XmppActivity {
if (!receive.isChecked()) {
if (online) {
contact.resetOption(Contact.Options.TO);
- activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
+ packet = xcs.getPresenceGenerator().stopPresenceUpdatesFrom(contact);
}
updated = true;
}
@@ -347,8 +343,7 @@ public class ContactDetailsActivity extends XmppActivity {
if (!receive.isChecked()) {
if (online) {
contact.resetOption(Contact.Options.ASKING);
- activity.xmppConnectionService
- .stopPresenceUpdatesFrom(contact);
+ packet = xcs.getPresenceGenerator().stopPresenceUpdatesFrom(contact);
}
updated = true;
}
@@ -356,8 +351,7 @@ public class ContactDetailsActivity extends XmppActivity {
if (receive.isChecked()) {
if (online) {
contact.setOption(Contact.Options.ASKING);
- activity.xmppConnectionService
- .requestPresenceUpdatesFrom(contact);
+ packet = xcs.getPresenceGenerator().requestPresenceUpdatesFrom(contact);
}
updated = true;
}
@@ -365,6 +359,9 @@ public class ContactDetailsActivity extends XmppActivity {
}
if (updated) {
if (online) {
+ if (packet!=null) {
+ xcs.sendPresencePacket(contact.getAccount(), packet);
+ }
Toast.makeText(getApplicationContext(), getString(R.string.subscription_updated), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), getString(R.string.subscription_not_updated_offline), Toast.LENGTH_SHORT).show();
diff --git a/src/eu/siacs/conversations/ui/ContactsActivity.java b/src/eu/siacs/conversations/ui/ContactsActivity.java
deleted file mode 100644
index fee3de7a..00000000
--- a/src/eu/siacs/conversations/ui/ContactsActivity.java
+++ /dev/null
@@ -1,598 +0,0 @@
-package eu.siacs.conversations.ui;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Contact;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.utils.CryptoHelper;
-import eu.siacs.conversations.utils.UIHelper;
-import eu.siacs.conversations.utils.Validator;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.text.Editable;
-import android.text.TextWatcher;
-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;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.ImageView;
-import android.widget.Toast;
-import android.annotation.SuppressLint;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-
-public class ContactsActivity extends XmppActivity {
-
- protected List<Contact> rosterContacts = new ArrayList<Contact>();
- protected List<Contact> aggregatedContacts = new ArrayList<Contact>();
- protected ListView contactsView;
- protected ArrayAdapter<Contact> contactsAdapter;
-
- protected EditText search;
- protected String searchString = "";
- private TextView contactsHeader;
- private List<Account> accounts;
- private List<Contact> selectedContacts = new ArrayList<Contact>();
-
- private ContactsActivity activity = this;
-
- private boolean useSubject = true;
- private boolean isActionMode = false;
- private boolean inviteIntent = 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);
- menu.findItem(R.id.action_invite).setVisible(false);
- menu.findItem(R.id.action_invite_to_existing).setVisible(false);
- } else if ((selectedContacts.size() == 1) && (!inviteIntent)) {
- menu.findItem(R.id.action_start_conversation).setVisible(true);
- menu.findItem(R.id.action_contact_details).setVisible(true);
- menu.findItem(R.id.action_invite).setVisible(false);
- menu.findItem(R.id.action_invite_to_existing).setVisible(true);
- } else if (!inviteIntent) {
- menu.findItem(R.id.action_start_conversation).setVisible(true);
- menu.findItem(R.id.action_contact_details).setVisible(false);
- menu.findItem(R.id.action_invite).setVisible(false);
- menu.findItem(R.id.action_invite_to_existing).setVisible(true);
- } else {
- menu.findItem(R.id.action_invite).setVisible(true);
- menu.findItem(R.id.action_start_conversation).setVisible(false);
- menu.findItem(R.id.action_contact_details).setVisible(false);
- menu.findItem(R.id.action_invite_to_existing).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("account", selectedContacts.get(0).getAccount().getJid());
- intent.putExtra("contact",selectedContacts.get(0).getJid());
- startActivity(intent);
- finish();
- break;
- case R.id.action_invite:
- invite();
- break;
- case R.id.action_invite_to_existing:
- final List<Conversation> mucs = new ArrayList<Conversation>();
- for(Conversation conv : xmppConnectionService.getConversations()) {
- if (conv.getMode() == Conversation.MODE_MULTI) {
- mucs.add(conv);
- }
- }
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(getString(R.string.invite_contacts_to_existing));
- if (mucs.size() >= 1) {
- String[] options = new String[mucs.size()];
- for(int i = 0; i < options.length; ++i) {
- options[i] = mucs.get(i).getName(useSubject);
- }
- builder.setItems(options, new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Conversation conversation = mucs.get(which);
- if (isOnline(conversation.getAccount())) {
- xmppConnectionService.inviteToConference(conversation, selectedContacts);
- Toast.makeText(activity, getString(R.string.invitation_sent), Toast.LENGTH_SHORT).show();
- actionMode.finish();
- }
- }
- });
- } else {
- builder.setMessage(getString(R.string.no_open_mucs));
- }
- builder.setNegativeButton(getString(R.string.cancel),null);
- builder.create().show();
- break;
- default:
- break;
- }
- return false;
- }
-
- @Override
- public void onItemCheckedStateChanged(ActionMode mode, int position,
- long id, boolean checked) {
- }
- };
-
- private boolean isOnline(Account account) {
- if (account.getStatus() == Account.STATUS_ONLINE) {
- return true;
- } else {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(getString(R.string.account_offline));
- builder.setMessage(getString(R.string.cant_invite_while_offline));
- builder.setNegativeButton(getString(R.string.ok), null);
- builder.setIconAttribute(android.R.attr.alertDialogIcon);
- builder.create().show();
- return false;
- }
- }
-
- private void invite() {
- List<Conversation> conversations = xmppConnectionService
- .getConversations();
- Conversation conversation = null;
- for (Conversation tmpConversation : conversations) {
- if (tmpConversation.getUuid().equals(
- getIntent().getStringExtra("uuid"))) {
- conversation = tmpConversation;
- break;
- }
- }
- if (conversation != null) {
- xmppConnectionService.inviteToConference(conversation,
- selectedContacts);
- }
- finish();
- }
-
- private void startConference() {
- if (accounts.size() > 1) {
- getAccountChooser(new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- startConference(accounts.get(which));
- }
- }).show();
- } else {
- startConference(accounts.get(0));
- }
-
- }
-
- private void startConference(final Account account) {
- if (isOnline(account)) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(getString(R.string.new_conference));
- builder.setMessage(getString(R.string.new_conference_explained));
- builder.setNegativeButton(getString(R.string.cancel), null);
- builder.setPositiveButton(getString(R.string.create_invite),
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String mucName = CryptoHelper.randomMucName(xmppConnectionService.getRNG());
- String serverName = account.getXmppConnection()
- .getMucServer();
- if (serverName==null) {
- List<String> servers = getMucServers();
- if (servers.size() >= 1) {
- serverName = servers.get(0);
- } else {
- displayErrorDialog(R.string.no_muc_server_found);
- return;
- }
- }
- String jid = mucName + "@" + serverName;
- Conversation conversation = xmppConnectionService
- .findOrCreateConversation(account, jid, true);
- StringBuilder subject = new StringBuilder();
- subject.append(account.getUsername() + ", ");
- 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,
- selectedContacts);
- switchToConversation(conversation, null,false);
- }
- });
- builder.create().show();
- }
- }
-
- protected void updateAggregatedContacts() {
-
- aggregatedContacts.clear();
- for (Contact contact : rosterContacts) {
- if (contact.match(searchString)&&(contact.showInRoster()))
- aggregatedContacts.add(contact);
- }
-
- Collections.sort(aggregatedContacts, new Comparator<Contact>() {
-
- @SuppressLint("DefaultLocale")
- @Override
- public int compare(Contact lhs, Contact rhs) {
- return lhs.getDisplayName().toLowerCase()
- .compareTo(rhs.getDisplayName().toLowerCase());
- }
- });
-
- if (aggregatedContacts.size() == 0) {
-
- if (Validator.isValidJid(searchString)) {
- Contact newContact = new Contact(searchString);
- newContact.resetOption(Contact.Options.IN_ROSTER);
- aggregatedContacts.add(newContact);
- contactsHeader.setText(getString(R.string.new_contact));
- } else {
- contactsHeader.setText(getString(R.string.contacts));
- }
- } else {
- contactsHeader.setText(getString(R.string.contacts));
- }
-
- 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 onStart() {
- super.onStart();
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
- this.useSubject = preferences.getBoolean("use_subject_in_muc", true);
- inviteIntent = "invite".equals(getIntent().getAction());
- if (inviteIntent) {
- contactsHeader.setVisibility(View.GONE);
- actionMode = contactsView.startActionMode(actionModeCallback);
- search.setVisibility(View.GONE);
- }
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_new_conversation);
-
- contactsHeader = (TextView) findViewById(R.id.contacts_header);
-
- search = (EditText) findViewById(R.id.new_conversation_search);
- search.addTextChangedListener(new TextWatcher() {
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before,
- int count) {
- searchString = search.getText().toString();
- updateAggregatedContacts();
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
- // TODO Auto-generated method stub
-
- }
- });
-
- contactsView = (ListView) findViewById(R.id.contactList);
- contactsAdapter = new ArrayAdapter<Contact>(getApplicationContext(),
- R.layout.contact, aggregatedContacts) {
- @Override
- public View getView(int position, View view, ViewGroup parent) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- Contact contact = getItem(position);
- if (view == null) {
- view = (View) inflater.inflate(R.layout.contact, null);
- }
-
- ((TextView) view.findViewById(R.id.contact_display_name))
- .setText(getItem(position).getDisplayName());
- TextView contactJid = (TextView) view
- .findViewById(R.id.contact_jid);
- contactJid.setText(contact.getJid());
- ImageView imageView = (ImageView) view
- .findViewById(R.id.contact_photo);
- imageView.setImageBitmap(UIHelper.getContactPicture(contact, 48, this.getContext(), false));
- return view;
- }
- };
- contactsView.setAdapter(contactsAdapter);
- contactsView.setMultiChoiceModeListener(actionModeCallback);
- contactsView.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> arg0, final View view,
- int pos, long arg3) {
- if (!isActionMode) {
- Contact clickedContact = aggregatedContacts.get(pos);
- startConversation(clickedContact);
-
- } else {
- actionMode.invalidate();
- }
- }
- });
- contactsView.setOnItemLongClickListener(this.onLongClickListener);
- }
-
- public void startConversation(final Contact contact) {
- if ((contact.getAccount() == null) && (accounts.size() > 1)) {
- getAccountChooser(new OnClickListener() {
-
- @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) {
- String[] accountList = new String[accounts.size()];
- for (int i = 0; i < accounts.size(); ++i) {
- accountList[i] = accounts.get(i).getJid();
- }
-
- AlertDialog.Builder accountChooser = new AlertDialog.Builder(this);
- accountChooser.setTitle(getString(R.string.choose_account));
- accountChooser.setItems(accountList, listener);
- return accountChooser.create();
- }
-
- public void showIsMucDialogIfNeeded(final Contact clickedContact) {
- if (isMuc(clickedContact)) {
- startConversation(clickedContact,clickedContact.getAccount(), true);
- } else if (clickedContact.couldBeMuc()) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
- dialog.setTitle(getString(R.string.multi_user_conference));
- dialog.setMessage(getString(R.string.trying_join_conference));
- dialog.setPositiveButton(getString(R.string.yes), new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- startConversation(clickedContact,
- clickedContact.getAccount(), true);
- }
- });
- dialog.setNegativeButton(getString(R.string.no), new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- startConversation(clickedContact,
- clickedContact.getAccount(), false);
- }
- });
- dialog.create().show();
- } else {
- startConversation(clickedContact, clickedContact.getAccount(),
- false);
- }
- }
-
- private List<String> getMucServers() {
- ArrayList<String> mucServers = new ArrayList<String>();
- for(Account account : accounts) {
- if (account.getXmppConnection()!=null) {
- String server = account.getXmppConnection().getMucServer();
- if (server!=null) {
- mucServers.add(server);
- }
- }
- }
- return mucServers;
- }
-
- private boolean isMuc(Contact contact) {
- String[] parts = contact.getJid().split("@");
- if (parts.length != 2) {
- return false;
- }
- return getMucServers().contains(parts[1]);
- }
-
- public void startConversation(Contact contact, Account account, boolean muc) {
- if (!contact.getOption(Contact.Options.IN_ROSTER)&&(!muc)) {
- xmppConnectionService.createContact(contact);
- }
- Conversation conversation = xmppConnectionService
- .findOrCreateConversation(account, contact.getJid(), muc);
-
- switchToConversation(conversation, null,false);
- }
-
- @Override
- void onBackendConnected() {
- this.accounts = xmppConnectionService.getAccounts();
- if (Intent.ACTION_SENDTO.equals(getIntent().getAction())) {
- getActionBar().setDisplayHomeAsUpEnabled(false);
- getActionBar().setHomeButtonEnabled(false);
- String jid;
- try {
- jid = URLDecoder.decode(getIntent().getData().getEncodedPath(),
- "UTF-8").split("/")[1];
- } catch (UnsupportedEncodingException e) {
- jid = null;
- }
- if (jid != null) {
- final String finalJid = jid;
- if (this.accounts.size() > 1) {
- getAccountChooser(new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Conversation conversation = xmppConnectionService
- .findOrCreateConversation(
- accounts.get(which), finalJid,
- false);
- switchToConversation(conversation, null,false);
- finish();
- }
- }).show();
- } else {
- Conversation conversation = xmppConnectionService
- .findOrCreateConversation(this.accounts.get(0),
- jid, false);
- switchToConversation(conversation, null,false);
- finish();
- }
- }
- }
-
- if (xmppConnectionService.getConversationCount() == 0) {
- getActionBar().setDisplayHomeAsUpEnabled(false);
- getActionBar().setHomeButtonEnabled(false);
- }
- this.rosterContacts.clear();
- for(Account account : accounts) {
- if (account.getStatus() != Account.STATUS_DISABLED) {
- rosterContacts.addAll(account.getRoster().getContacts());
- }
- }
- updateAggregatedContacts();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.newconversation, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- default:
- break;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onActionModeStarted(ActionMode mode) {
- super.onActionModeStarted(mode);
- this.isActionMode = true;
- search.setEnabled(false);
- }
-
- @Override
- public void onActionModeFinished(ActionMode mode) {
- super.onActionModeFinished(mode);
- if (inviteIntent) {
- finish();
- } else {
- this.isActionMode = false;
- contactsView.clearChoices();
- contactsView.requestLayout();
- contactsView.post(new Runnable() {
- @Override
- public void run() {
- contactsView.setChoiceMode(ListView.CHOICE_MODE_NONE);
- }
- });
- search.setEnabled(true);
- }
- }
-
-}
diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java
index 03ced289..66db353b 100644
--- a/src/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/eu/siacs/conversations/ui/ConversationActivity.java
@@ -10,6 +10,7 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.ImageProvider;
+import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.UIHelper;
import android.net.Uri;
@@ -83,10 +84,10 @@ public class ConversationActivity extends XmppActivity {
private boolean showLastseen = false;
private ArrayAdapter<Conversation> listAdapter;
- private OnConversationListChangedListener onConvChanged = new OnConversationListChangedListener() {
-
+ private OnConversationUpdate onConvChanged = new OnConversationUpdate() {
+
@Override
- public void onConversationListChanged() {
+ public void onConversationUpdate() {
runOnUiThread(new Runnable() {
@Override
@@ -97,7 +98,7 @@ public class ConversationActivity extends XmppActivity {
swapConversationFragment();
} else {
startActivity(new Intent(getApplicationContext(),
- ContactsActivity.class));
+ StartConversation.class));
finish();
}
}
@@ -419,37 +420,6 @@ public class ConversationActivity extends XmppActivity {
selectPresenceToAttachFile(attachmentChoice);
} else {
selectPresenceToAttachFile(attachmentChoice);
- /*AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(getString(R.string.otr_file_transfer));
- builder.setMessage(getString(R.string.otr_file_transfer_msg));
- builder.setNegativeButton(getString(R.string.cancel), null);
- if (conversation.getContact().getPgpKeyId() == 0) {
- builder.setPositiveButton(getString(R.string.send_unencrypted),
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- conversation
- .setNextEncryption(Message.ENCRYPTION_NONE);
- attachFile(attachmentChoice);
- }
- });
- } else {
- builder.setPositiveButton(
- getString(R.string.use_pgp_encryption),
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- conversation
- .setNextEncryption(Message.ENCRYPTION_PGP);
- attachFile(attachmentChoice);
- }
- });
- }
- builder.create().show();*/
}
}
@@ -488,7 +458,7 @@ public class ConversationActivity extends XmppActivity {
attachFilePopup.show();
break;
case R.id.action_add:
- startActivity(new Intent(this, ContactsActivity.class));
+ startActivity(new Intent(this, StartConversation.class));
break;
case R.id.action_archive:
this.endConversation(getSelectedConversation());
@@ -496,12 +466,7 @@ public class ConversationActivity extends XmppActivity {
case R.id.action_contact_details:
Contact contact = this.getSelectedConversation().getContact();
if (contact.showInRoster()) {
- Intent intent = new Intent(this, ContactDetailsActivity.class);
- intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
- intent.putExtra("account", this.getSelectedConversation()
- .getAccount().getJid());
- intent.putExtra("contact", contact.getJid());
- startActivity(intent);
+ switchToContactDetails(contact);
} else {
showAddToRosterDialog(getSelectedConversation());
}
@@ -513,11 +478,11 @@ public class ConversationActivity extends XmppActivity {
startActivity(intent);
break;
case R.id.action_invite:
- Intent inviteIntent = new Intent(getApplicationContext(),
+ /*Intent inviteIntent = new Intent(getApplicationContext(),
ContactsActivity.class);
inviteIntent.setAction("invite");
inviteIntent.putExtra("uuid", getSelectedConversation().getUuid());
- startActivity(inviteIntent);
+ startActivity(inviteIntent);*/
break;
case R.id.action_security:
final Conversation conversation = getSelectedConversation();
@@ -691,7 +656,7 @@ public class ConversationActivity extends XmppActivity {
this.onBackendConnected();
}
if (conversationList.size() >= 1) {
- onConvChanged.onConversationListChanged();
+ onConvChanged.onConversationUpdate();
}
}
@@ -734,7 +699,7 @@ public class ConversationActivity extends XmppActivity {
finish();
} else if (conversationList.size() <= 0) {
// add no history
- startActivity(new Intent(this, ContactsActivity.class));
+ startActivity(new Intent(this, StartConversation.class));
finish();
} else {
spl.openPane();
@@ -768,7 +733,7 @@ public class ConversationActivity extends XmppActivity {
ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
.findFragmentByTag("conversation");
if (selectedFragment != null) {
- selectedFragment.hidePgpPassphraseBox();
+ selectedFragment.hideSnackbar();
}
} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
attachImageToConversation(getSelectedConversation(),
@@ -841,8 +806,7 @@ public class ConversationActivity extends XmppActivity {
}
public void updateConversationList() {
- conversationList.clear();
- conversationList.addAll(xmppConnectionService.getConversations());
+ xmppConnectionService.populateWithOrderedConversations(conversationList);
listView.invalidateViews();
}
diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java
index 1e703b48..01bab773 100644
--- a/src/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/eu/siacs/conversations/ui/ConversationFragment.java
@@ -48,6 +48,7 @@ import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -60,11 +61,17 @@ public class ConversationFragment extends Fragment {
protected ArrayAdapter<Message> messageListAdapter;
protected Contact contact;
protected BitmapCache mBitmapCache = new BitmapCache();
+
+ protected int mPrimaryTextColor;
+ protected int mSecondaryTextColor;
protected String queuedPqpMessage = null;
private EditText chatMsg;
private String pastedText = null;
+ private RelativeLayout snackbar;
+ private TextView snackbarMessage;
+ private TextView snackbarAction;
protected Bitmap selfBitmap;
@@ -106,10 +113,7 @@ public class ConversationFragment extends Fragment {
}
}
};
-
- private LinearLayout pgpInfo;
- private LinearLayout mucError;
- private TextView mucErrorText;
+
private OnClickListener clickToMuc = new OnClickListener() {
@Override
@@ -149,10 +153,6 @@ public class ConversationFragment extends Fragment {
private ConversationActivity activity;
- public void hidePgpPassphraseBox() {
- pgpInfo.setVisibility(View.GONE);
- }
-
public void updateChatMsgHint() {
switch (conversation.getNextEncryption()) {
case Message.ENCRYPTION_NONE:
@@ -177,6 +177,9 @@ public class ConversationFragment extends Fragment {
this.inflater = inflater;
+ mPrimaryTextColor = getResources().getColor(R.color.primarytext);
+ mSecondaryTextColor = getResources().getColor(R.color.secondarytext);
+
final View view = inflater.inflate(R.layout.fragment_conversation,
container, false);
chatMsg = (EditText) view.findViewById(R.id.textinput);
@@ -185,11 +188,9 @@ public class ConversationFragment extends Fragment {
.findViewById(R.id.textSendButton);
sendButton.setOnClickListener(this.sendMsgListener);
- pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
- pgpInfo.setOnClickListener(clickToDecryptListener);
- mucError = (LinearLayout) view.findViewById(R.id.muc_error);
- mucError.setOnClickListener(clickToMuc);
- mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
+ snackbar = (RelativeLayout) view.findViewById(R.id.snackbar);
+ snackbarMessage = (TextView) view.findViewById(R.id.snackbar_message);
+ snackbarAction = (TextView) view.findViewById(R.id.snackbar_action);
messagesView = (ListView) view.findViewById(R.id.messages_view);
messagesView.setOnScrollListener(mOnScrollListener);
@@ -264,7 +265,7 @@ public class ConversationFragment extends Fragment {
if (error) {
viewHolder.time.setTextColor(0xFFe92727);
} else {
- viewHolder.time.setTextColor(0xFF8e8e8e);
+ viewHolder.time.setTextColor(mSecondaryTextColor);
}
if (message.getEncryption() == Message.ENCRYPTION_NONE) {
viewHolder.indicator.setVisibility(View.GONE);
@@ -341,7 +342,7 @@ public class ConversationFragment extends Fragment {
} else {
viewHolder.messageBody.setText("");
}
- viewHolder.messageBody.setTextColor(0xff333333);
+ viewHolder.messageBody.setTextColor(mPrimaryTextColor);
viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
viewHolder.messageBody.setTextIsSelectable(true);
}
@@ -682,7 +683,7 @@ public class ConversationFragment extends Fragment {
@Override
public void userInputRequried(PendingIntent pi, Message message) {
askForPassphraseIntent = pi.getIntentSender();
- pgpInfo.setVisibility(View.VISIBLE);
+ showSnackbar(R.string.openpgp_messages_found,R.string.decrypt,clickToDecryptListener);
}
@Override
@@ -698,8 +699,6 @@ public class ConversationFragment extends Fragment {
// updateMessages();
}
});
- } else {
- pgpInfo.setVisibility(View.GONE);
}
}
@@ -736,12 +735,10 @@ public class ConversationFragment extends Fragment {
}
} else {
if (conversation.getMucOptions().getError() != 0) {
- mucError.setVisibility(View.VISIBLE);
+ showSnackbar(R.string.nick_in_use, R.string.edit,clickToMuc);
if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
- mucErrorText.setText(getString(R.string.nick_in_use));
+ showSnackbar(R.string.nick_in_use, R.string.edit,clickToMuc);
}
- } else {
- mucError.setVisibility(View.GONE);
}
}
getActivity().invalidateOptionsMenu();
@@ -789,34 +786,37 @@ public class ConversationFragment extends Fragment {
}
protected void makeFingerprintWarning(int latestEncryption) {
- final LinearLayout fingerprintWarning = (LinearLayout) getView()
- .findViewById(R.id.new_fingerprint);
Set<String> knownFingerprints = conversation.getContact()
.getOtrFingerprints();
if ((latestEncryption == Message.ENCRYPTION_OTR)
&& (conversation.hasValidOtrSession()
&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
.contains(conversation.getOtrFingerprint())))) {
- fingerprintWarning.setVisibility(View.VISIBLE);
- TextView fingerprint = (TextView) getView().findViewById(
- R.id.otr_fingerprint);
- fingerprint.setText(conversation.getOtrFingerprint());
- fingerprintWarning.setOnClickListener(new OnClickListener() {
+ showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, new OnClickListener() {
@Override
public void onClick(View v) {
if (conversation.getOtrFingerprint() != null) {
AlertDialog dialog = UIHelper.getVerifyFingerprintDialog(
(ConversationActivity) getActivity(), conversation,
- fingerprintWarning);
+ snackbar);
dialog.show();
}
}
});
- } else {
- fingerprintWarning.setVisibility(View.GONE);
}
}
+
+ protected void showSnackbar(int message, int action, OnClickListener clickListener) {
+ snackbar.setVisibility(View.VISIBLE);
+ snackbarMessage.setText(message);
+ snackbarAction.setText(action);
+ snackbarAction.setOnClickListener(clickListener);
+ }
+
+ protected void hideSnackbar() {
+ snackbar.setVisibility(View.GONE);
+ }
protected void sendPlainTextMessage(Message message) {
ConversationActivity activity = (ConversationActivity) getActivity();
diff --git a/src/eu/siacs/conversations/ui/EditAccount.java b/src/eu/siacs/conversations/ui/EditAccount.java
index e1bcaeb5..9a0b8d84 100644
--- a/src/eu/siacs/conversations/ui/EditAccount.java
+++ b/src/eu/siacs/conversations/ui/EditAccount.java
@@ -1,14 +1,19 @@
package eu.siacs.conversations.ui;
+import java.util.List;
+
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.utils.KnownHostsAdapter;
import eu.siacs.conversations.utils.Validator;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
+import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
@@ -19,6 +24,8 @@ import android.widget.TextView;
public class EditAccount extends DialogFragment {
protected Account account;
+
+ protected AutoCompleteTextView mAccountJid;
public void setAccount(Account account) {
this.account = account;
@@ -30,16 +37,28 @@ public class EditAccount extends DialogFragment {
protected EditAccountListener listener = null;
+ private KnownHostsAdapter mKnownHostsAdapter;
+
public void setEditAccountListener(EditAccountListener listener) {
this.listener = listener;
}
+
+ public void setKnownHosts(List<String> hosts, Context context) {
+ this.mKnownHostsAdapter = new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, hosts);
+ if (this.mAccountJid != null) {
+ this.mAccountJid.setAdapter(this.mKnownHostsAdapter);
+ }
+ }
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.edit_account_dialog, null);
- final EditText jidText = (EditText) view.findViewById(R.id.account_jid);
+ mAccountJid = (AutoCompleteTextView) view.findViewById(R.id.account_jid);
+ if (this.mKnownHostsAdapter!=null) {
+ mAccountJid.setAdapter(this.mKnownHostsAdapter);
+ }
final TextView confirmPwDesc = (TextView) view
.findViewById(R.id.account_confirm_password_desc);
@@ -51,7 +70,7 @@ public class EditAccount extends DialogFragment {
.findViewById(R.id.edit_account_register_new);
if (account != null) {
- jidText.setText(account.getJid());
+ mAccountJid.setText(account.getJid());
password.setText(account.getPassword());
if (account.isOptionSet(Account.OPTION_REGISTER)) {
registerAccount.setChecked(true);
diff --git a/src/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/eu/siacs/conversations/ui/ManageAccountActivity.java
index c52916a2..c3f1e105 100644
--- a/src/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -5,6 +5,7 @@ import java.util.List;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.ui.EditAccount.EditAccountListener;
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
import eu.siacs.conversations.xmpp.XmppConnection;
@@ -31,21 +32,21 @@ import android.widget.ListView;
import android.widget.TextView;
public class ManageAccountActivity extends XmppActivity {
-
+
protected boolean isActionMode = false;
protected ActionMode actionMode;
protected Account selectedAccountForActionMode = null;
protected ManageAccountActivity activity = this;
-
+
protected boolean firstrun = true;
-
+
protected List<Account> accountList = new ArrayList<Account>();
protected ListView accountListView;
protected ArrayAdapter<Account> accountListViewAdapter;
- protected OnAccountListChangedListener accountChanged = new OnAccountListChangedListener() {
+ protected OnAccountUpdate accountChanged = new OnAccountUpdate() {
@Override
- public void onAccountListChangedListener() {
+ public void onAccountUpdate() {
accountList.clear();
accountList.addAll(xmppConnectionService.getAccounts());
runOnUiThread(new Runnable() {
@@ -57,47 +58,55 @@ public class ManageAccountActivity extends XmppActivity {
});
}
};
-
+
protected OnTLSExceptionReceived tlsExceptionReceived = new OnTLSExceptionReceived() {
-
+
@Override
- public void onTLSExceptionReceived(final String fingerprint, final Account account) {
+ public void onTLSExceptionReceived(final String fingerprint,
+ final Account account) {
activity.runOnUiThread(new Runnable() {
-
+
@Override
public void run() {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ activity);
builder.setTitle(getString(R.string.account_status_error));
builder.setIconAttribute(android.R.attr.alertDialogIcon);
- View view = (View) getLayoutInflater().inflate(R.layout.cert_warning, null);
+ View view = (View) getLayoutInflater().inflate(
+ R.layout.cert_warning, null);
TextView sha = (TextView) view.findViewById(R.id.sha);
TextView hint = (TextView) view.findViewById(R.id.hint);
StringBuilder humanReadableSha = new StringBuilder();
humanReadableSha.append(fingerprint);
- for(int i = 2; i < 59; i += 3) {
- if ((i==14)||(i==29)||(i==44)) {
+ for (int i = 2; i < 59; i += 3) {
+ if ((i == 14) || (i == 29) || (i == 44)) {
humanReadableSha.insert(i, "\n");
} else {
humanReadableSha.insert(i, ":");
}
-
+
}
- hint.setText(getString(R.string.untrusted_cert_hint,account.getServer()));
+ hint.setText(getString(R.string.untrusted_cert_hint,
+ account.getServer()));
sha.setText(humanReadableSha.toString());
builder.setView(view);
- builder.setNegativeButton(getString(R.string.certif_no_trust), null);
- builder.setPositiveButton(getString(R.string.certif_trust), new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- account.setSSLCertFingerprint(fingerprint);
- activity.xmppConnectionService.updateAccount(account);
- }
- });
+ builder.setNegativeButton(
+ getString(R.string.certif_no_trust), null);
+ builder.setPositiveButton(getString(R.string.certif_trust),
+ new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog,
+ int which) {
+ account.setSSLCertFingerprint(fingerprint);
+ activity.xmppConnectionService
+ .updateAccount(account);
+ }
+ });
builder.create().show();
}
});
-
+
}
};
@@ -124,55 +133,68 @@ public class ManageAccountActivity extends XmppActivity {
.findViewById(R.id.account_status);
switch (account.getStatus()) {
case Account.STATUS_DISABLED:
- statusView.setText(getString(R.string.account_status_disabled));
+ statusView
+ .setText(getString(R.string.account_status_disabled));
statusView.setTextColor(0xFF1da9da);
break;
case Account.STATUS_ONLINE:
- statusView.setText(getString(R.string.account_status_online));
+ statusView
+ .setText(getString(R.string.account_status_online));
statusView.setTextColor(0xFF83b600);
break;
case Account.STATUS_CONNECTING:
- statusView.setText(getString(R.string.account_status_connecting));
+ statusView
+ .setText(getString(R.string.account_status_connecting));
statusView.setTextColor(0xFF1da9da);
break;
case Account.STATUS_OFFLINE:
- statusView.setText(getString(R.string.account_status_offline));
+ statusView
+ .setText(getString(R.string.account_status_offline));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_UNAUTHORIZED:
- statusView.setText(getString(R.string.account_status_unauthorized));
+ statusView
+ .setText(getString(R.string.account_status_unauthorized));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_SERVER_NOT_FOUND:
- statusView.setText(getString(R.string.account_status_not_found));
+ statusView
+ .setText(getString(R.string.account_status_not_found));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_NO_INTERNET:
- statusView.setText(getString(R.string.account_status_no_internet));
+ statusView
+ .setText(getString(R.string.account_status_no_internet));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_SERVER_REQUIRES_TLS:
- statusView.setText(getString(R.string.account_status_requires_tls));
+ statusView
+ .setText(getString(R.string.account_status_requires_tls));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_TLS_ERROR:
- statusView.setText(getString(R.string.account_status_error));
+ statusView
+ .setText(getString(R.string.account_status_error));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_REGISTRATION_FAILED:
- statusView.setText(getString(R.string.account_status_regis_fail));
+ statusView
+ .setText(getString(R.string.account_status_regis_fail));
statusView.setTextColor(0xFFe92727);
break;
case Account.STATUS_REGISTRATION_CONFLICT:
- statusView.setText(getString(R.string.account_status_regis_conflict));
+ statusView
+ .setText(getString(R.string.account_status_regis_conflict));
statusView.setTextColor(0xFFe92727);
break;
- case Account.STATUS_REGISTRATION_SUCCESSFULL:
- statusView.setText(getString(R.string.account_status_regis_success));
+ case Account.STATUS_REGISTRATION_SUCCESSFULL:
+ statusView
+ .setText(getString(R.string.account_status_regis_success));
statusView.setTextColor(0xFF83b600);
break;
case Account.STATUS_REGISTRATION_NOT_SUPPORTED:
- statusView.setText(getString(R.string.account_status_regis_not_sup));
+ statusView
+ .setText(getString(R.string.account_status_regis_not_sup));
statusView.setTextColor(0xFFe92727);
break;
default:
@@ -192,10 +214,14 @@ public class ManageAccountActivity extends XmppActivity {
int position, long arg3) {
if (!isActionMode) {
Account account = accountList.get(position);
- if ((account.getStatus() == Account.STATUS_OFFLINE)||(account.getStatus() == Account.STATUS_TLS_ERROR)) {
- activity.xmppConnectionService.reconnectAccount(accountList.get(position),true);
+ if ((account.getStatus() == Account.STATUS_OFFLINE)
+ || (account.getStatus() == Account.STATUS_TLS_ERROR)) {
+ activity.xmppConnectionService.reconnectAccount(
+ accountList.get(position), true);
} else if (account.getStatus() == Account.STATUS_ONLINE) {
- activity.startActivity(new Intent(activity.getApplicationContext(),ContactsActivity.class));
+ activity.startActivity(new Intent(activity
+ .getApplicationContext(),
+ StartConversation.class));
} else if (account.getStatus() != Account.STATUS_DISABLED) {
editAccount(account);
}
@@ -205,159 +231,242 @@ public class ManageAccountActivity extends XmppActivity {
}
}
});
- accountListView.setOnItemLongClickListener(new OnItemLongClickListener() {
+ accountListView
+ .setOnItemLongClickListener(new OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView<?> arg0, View view,
- int position, long arg3) {
- if (!isActionMode) {
- accountListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- accountListView.setItemChecked(position,true);
- selectedAccountForActionMode = accountList.get(position);
- actionMode = activity.startActionMode((new ActionMode.Callback() {
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- if (selectedAccountForActionMode.isOptionSet(Account.OPTION_DISABLED)) {
- menu.findItem(R.id.mgmt_account_enable).setVisible(true);
- menu.findItem(R.id.mgmt_account_disable).setVisible(false);
- } else {
- menu.findItem(R.id.mgmt_account_disable).setVisible(true);
- menu.findItem(R.id.mgmt_account_enable).setVisible(false);
- }
- return true;
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- MenuInflater inflater = mode.getMenuInflater();
- inflater.inflate(R.menu.manageaccounts_context, menu);
- return true;
- }
-
- @Override
- public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
- if (item.getItemId()==R.id.mgmt_account_edit) {
- editAccount(selectedAccountForActionMode);
- } else if (item.getItemId()==R.id.mgmt_account_disable) {
- selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, true);
- xmppConnectionService.updateAccount(selectedAccountForActionMode);
- mode.finish();
- } else if (item.getItemId()==R.id.mgmt_account_enable) {
- selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, false);
- xmppConnectionService.updateAccount(selectedAccountForActionMode);
- mode.finish();
- } else if (item.getItemId()==R.id.mgmt_account_delete) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
- builder.setIconAttribute(android.R.attr.alertDialogIcon);
- builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
- builder.setPositiveButton(getString(R.string.delete), new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- xmppConnectionService.deleteAccount(selectedAccountForActionMode);
- selectedAccountForActionMode = null;
- mode.finish();
- }
- });
- builder.setNegativeButton(getString(R.string.cancel),null);
- builder.create().show();
- } else if (item.getItemId()==R.id.mgmt_account_announce_pgp) {
- if (activity.hasPgp()) {
- mode.finish();
- announcePgp(selectedAccountForActionMode,null);
- } else {
- activity.showInstallPgpDialog();
- }
- } else if (item.getItemId() == R.id.mgmt_otr_key) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle("OTR Fingerprint");
- String fingerprintTxt = selectedAccountForActionMode.getOtrFingerprint(getApplicationContext());
- View view = (View) getLayoutInflater().inflate(R.layout.otr_fingerprint, null);
- if (fingerprintTxt!=null) {
- TextView fingerprint = (TextView) view.findViewById(R.id.otr_fingerprint);
- TextView noFingerprintView = (TextView) view.findViewById(R.id.otr_no_fingerprint);
- fingerprint.setText(fingerprintTxt);
- fingerprint.setVisibility(View.VISIBLE);
- noFingerprintView.setVisibility(View.GONE);
- }
- builder.setView(view);
- builder.setPositiveButton(getString(R.string.done), null);
- builder.create().show();
- } else if (item.getItemId() == R.id.mgmt_account_info) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(getString(R.string.account_info));
- if (selectedAccountForActionMode.getStatus() == Account.STATUS_ONLINE) {
- XmppConnection xmpp = selectedAccountForActionMode.getXmppConnection();
- long connectionAge = (SystemClock.elapsedRealtime() - xmpp.lastConnect) / 60000;
- long sessionAge = (SystemClock.elapsedRealtime() - xmpp.lastSessionStarted) / 60000;
- long connectionAgeHours = connectionAge / 60;
- long sessionAgeHours = sessionAge / 60;
- View view = (View) getLayoutInflater().inflate(R.layout.server_info, null);
- TextView connection = (TextView) view.findViewById(R.id.connection);
- TextView session = (TextView) view.findViewById(R.id.session);
- TextView pcks_sent = (TextView) view.findViewById(R.id.pcks_sent);
- TextView pcks_received = (TextView) view.findViewById(R.id.pcks_received);
- TextView carbon = (TextView) view.findViewById(R.id.carbon);
- TextView stream = (TextView) view.findViewById(R.id.stream);
- TextView roster = (TextView) view.findViewById(R.id.roster);
- TextView presences = (TextView) view.findViewById(R.id.number_presences);
- presences.setText(selectedAccountForActionMode.countPresences()+"");
- pcks_received.setText(""+xmpp.getReceivedStanzas());
- pcks_sent.setText(""+xmpp.getSentStanzas());
- if (connectionAgeHours >= 2) {
- connection.setText(connectionAgeHours+" " + getString(R.string.hours));
- } else {
- connection.setText(connectionAge+" " + getString(R.string.mins));
- }
- if (xmpp.hasFeatureStreamManagment()) {
- if (sessionAgeHours >= 2) {
- session.setText(sessionAgeHours+" " + getString(R.string.hours));
- } else {
- session.setText(sessionAge+" " + getString(R.string.mins));
+ @Override
+ public boolean onItemLongClick(AdapterView<?> arg0,
+ View view, int position, long arg3) {
+ if (!isActionMode) {
+ accountListView
+ .setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ accountListView.setItemChecked(position, true);
+ selectedAccountForActionMode = accountList
+ .get(position);
+ actionMode = activity
+ .startActionMode((new ActionMode.Callback() {
+
+ @Override
+ public boolean onPrepareActionMode(
+ ActionMode mode, Menu menu) {
+ if (selectedAccountForActionMode
+ .isOptionSet(Account.OPTION_DISABLED)) {
+ menu.findItem(
+ R.id.mgmt_account_enable)
+ .setVisible(true);
+ menu.findItem(
+ R.id.mgmt_account_disable)
+ .setVisible(false);
+ } else {
+ menu.findItem(
+ R.id.mgmt_account_disable)
+ .setVisible(true);
+ menu.findItem(
+ R.id.mgmt_account_enable)
+ .setVisible(false);
+ }
+ return true;
}
- stream.setText(getString(R.string.yes));
- } else {
- stream.setText(getString(R.string.no));
- session.setText(connection.getText());
- }
- if (xmpp.hasFeaturesCarbon()) {
- carbon.setText(getString(R.string.yes));
- } else {
- carbon.setText(getString(R.string.no));
- }
- if (xmpp.hasFeatureRosterManagment()) {
- roster.setText(getString(R.string.yes));
- } else {
- roster.setText(getString(R.string.no));
- }
- builder.setView(view);
- } else {
- builder.setMessage(getString(R.string.mgmt_account_account_offline));
- }
- builder.setPositiveButton(getString(R.string.hide), null);
- builder.create().show();
- }
+
+ @Override
+ public void onDestroyActionMode(
+ ActionMode mode) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean onCreateActionMode(
+ ActionMode mode, Menu menu) {
+ MenuInflater inflater = mode
+ .getMenuInflater();
+ inflater.inflate(
+ R.menu.manageaccounts_context,
+ menu);
+ return true;
+ }
+
+ @Override
+ public boolean onActionItemClicked(
+ final ActionMode mode,
+ MenuItem item) {
+ if (item.getItemId() == R.id.mgmt_account_edit) {
+ editAccount(selectedAccountForActionMode);
+ } else if (item.getItemId() == R.id.mgmt_account_disable) {
+ selectedAccountForActionMode
+ .setOption(
+ Account.OPTION_DISABLED,
+ true);
+ xmppConnectionService
+ .updateAccount(selectedAccountForActionMode);
+ mode.finish();
+ } else if (item.getItemId() == R.id.mgmt_account_enable) {
+ selectedAccountForActionMode
+ .setOption(
+ Account.OPTION_DISABLED,
+ false);
+ xmppConnectionService
+ .updateAccount(selectedAccountForActionMode);
+ mode.finish();
+ } else if (item.getItemId() == R.id.mgmt_account_delete) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ activity);
+ builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
+ builder.setIconAttribute(android.R.attr.alertDialogIcon);
+ builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
+ builder.setPositiveButton(
+ getString(R.string.delete),
+ new OnClickListener() {
+
+ @Override
+ public void onClick(
+ DialogInterface dialog,
+ int which) {
+ xmppConnectionService
+ .deleteAccount(selectedAccountForActionMode);
+ selectedAccountForActionMode = null;
+ mode.finish();
+ }
+ });
+ builder.setNegativeButton(
+ getString(R.string.cancel),
+ null);
+ builder.create().show();
+ } else if (item.getItemId() == R.id.mgmt_account_announce_pgp) {
+ if (activity.hasPgp()) {
+ mode.finish();
+ announcePgp(
+ selectedAccountForActionMode,
+ null);
+ } else {
+ activity.showInstallPgpDialog();
+ }
+ } else if (item.getItemId() == R.id.mgmt_otr_key) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ activity);
+ builder.setTitle("OTR Fingerprint");
+ String fingerprintTxt = selectedAccountForActionMode
+ .getOtrFingerprint(getApplicationContext());
+ View view = (View) getLayoutInflater()
+ .inflate(
+ R.layout.otr_fingerprint,
+ null);
+ if (fingerprintTxt != null) {
+ TextView fingerprint = (TextView) view
+ .findViewById(R.id.otr_fingerprint);
+ TextView noFingerprintView = (TextView) view
+ .findViewById(R.id.otr_no_fingerprint);
+ fingerprint
+ .setText(fingerprintTxt);
+ fingerprint
+ .setVisibility(View.VISIBLE);
+ noFingerprintView
+ .setVisibility(View.GONE);
+ }
+ builder.setView(view);
+ builder.setPositiveButton(
+ getString(R.string.done),
+ null);
+ builder.create().show();
+ } else if (item.getItemId() == R.id.mgmt_account_info) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ activity);
+ builder.setTitle(getString(R.string.account_info));
+ if (selectedAccountForActionMode
+ .getStatus() == Account.STATUS_ONLINE) {
+ XmppConnection xmpp = selectedAccountForActionMode
+ .getXmppConnection();
+ long connectionAge = (SystemClock
+ .elapsedRealtime() - xmpp.lastConnect) / 60000;
+ long sessionAge = (SystemClock
+ .elapsedRealtime() - xmpp.lastSessionStarted) / 60000;
+ long connectionAgeHours = connectionAge / 60;
+ long sessionAgeHours = sessionAge / 60;
+ View view = (View) getLayoutInflater()
+ .inflate(
+ R.layout.server_info,
+ null);
+ TextView connection = (TextView) view
+ .findViewById(R.id.connection);
+ TextView session = (TextView) view
+ .findViewById(R.id.session);
+ TextView pcks_sent = (TextView) view
+ .findViewById(R.id.pcks_sent);
+ TextView pcks_received = (TextView) view
+ .findViewById(R.id.pcks_received);
+ TextView carbon = (TextView) view
+ .findViewById(R.id.carbon);
+ TextView stream = (TextView) view
+ .findViewById(R.id.stream);
+ TextView roster = (TextView) view
+ .findViewById(R.id.roster);
+ TextView presences = (TextView) view
+ .findViewById(R.id.number_presences);
+ presences.setText(selectedAccountForActionMode
+ .countPresences()
+ + "");
+ pcks_received.setText(""
+ + xmpp.getReceivedStanzas());
+ pcks_sent.setText(""
+ + xmpp.getSentStanzas());
+ if (connectionAgeHours >= 2) {
+ connection
+ .setText(connectionAgeHours
+ + " "
+ + getString(R.string.hours));
+ } else {
+ connection
+ .setText(connectionAge
+ + " "
+ + getString(R.string.mins));
+ }
+ if (xmpp.hasFeatureStreamManagment()) {
+ if (sessionAgeHours >= 2) {
+ session.setText(sessionAgeHours
+ + " "
+ + getString(R.string.hours));
+ } else {
+ session.setText(sessionAge
+ + " "
+ + getString(R.string.mins));
+ }
+ stream.setText(getString(R.string.yes));
+ } else {
+ stream.setText(getString(R.string.no));
+ session.setText(connection
+ .getText());
+ }
+ if (xmpp.hasFeaturesCarbon()) {
+ carbon.setText(getString(R.string.yes));
+ } else {
+ carbon.setText(getString(R.string.no));
+ }
+ if (xmpp.hasFeatureRosterManagment()) {
+ roster.setText(getString(R.string.yes));
+ } else {
+ roster.setText(getString(R.string.no));
+ }
+ builder.setView(view);
+ } else {
+ builder.setMessage(getString(R.string.mgmt_account_account_offline));
+ }
+ builder.setPositiveButton(
+ getString(R.string.hide),
+ null);
+ builder.create().show();
+ }
+ return true;
+ }
+
+ }));
return true;
+ } else {
+ return false;
}
-
-
- }));
- return true;
- } else {
- return false;
- }
- }
- });
+ }
+ });
}
-
+
@Override
protected void onStop() {
if (xmppConnectionServiceBound) {
@@ -370,11 +479,12 @@ public class ManageAccountActivity extends XmppActivity {
@Override
void onBackendConnected() {
xmppConnectionService.setOnAccountListChangedListener(accountChanged);
- xmppConnectionService.setOnTLSExceptionReceivedListener(tlsExceptionReceived);
+ xmppConnectionService
+ .setOnTLSExceptionReceivedListener(tlsExceptionReceived);
this.accountList.clear();
this.accountList.addAll(xmppConnectionService.getAccounts());
accountListViewAdapter.notifyDataSetChanged();
- if ((this.accountList.size() == 0)&&(this.firstrun)) {
+ if ((this.accountList.size() == 0) && (this.firstrun)) {
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
addAccount();
@@ -403,14 +513,15 @@ public class ManageAccountActivity extends XmppActivity {
@Override
public boolean onNavigateUp() {
if (xmppConnectionService.getConversations().size() == 0) {
- Intent contactsIntent = new Intent(this, ContactsActivity.class);
+ Intent contactsIntent = new Intent(this, StartConversation.class);
contactsIntent.setFlags(
- // if activity exists in stack, pop the stack and go back to it
+ // if activity exists in stack, pop the stack and go back to it
Intent.FLAG_ACTIVITY_CLEAR_TOP |
// otherwise, make a new task for it
- Intent.FLAG_ACTIVITY_NEW_TASK |
- // don't use the new activity animation; finish animation runs instead
- Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ Intent.FLAG_ACTIVITY_NEW_TASK |
+ // don't use the new activity animation; finish
+ // animation runs instead
+ Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(contactsIntent);
finish();
return true;
@@ -420,22 +531,23 @@ public class ManageAccountActivity extends XmppActivity {
}
private void editAccount(Account account) {
- EditAccount dialog = new EditAccount();
- dialog.setAccount(account);
- dialog.setEditAccountListener(new EditAccountListener() {
+ EditAccount dialog = new EditAccount();
+ dialog.setAccount(account);
+ dialog.setEditAccountListener(new EditAccountListener() {
- @Override
- public void onAccountEdited(Account account) {
- xmppConnectionService.updateAccount(account);
- if (actionMode != null) {
- actionMode.finish();
- }
+ @Override
+ public void onAccountEdited(Account account) {
+ xmppConnectionService.updateAccount(account);
+ if (actionMode != null) {
+ actionMode.finish();
}
- });
- dialog.show(getFragmentManager(), "edit_account");
-
+ }
+ });
+ dialog.show(getFragmentManager(), "edit_account");
+ dialog.setKnownHosts(xmppConnectionService.getKnownHosts(), this);
+
}
-
+
protected void addAccount() {
final Activity activity = this;
EditAccount dialog = new EditAccount();
@@ -449,15 +561,15 @@ public class ManageAccountActivity extends XmppActivity {
}
});
dialog.show(getFragmentManager(), "add_account");
+ dialog.setKnownHosts(xmppConnectionService.getKnownHosts(), this);
}
-
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
this.isActionMode = true;
}
-
+
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
@@ -465,20 +577,20 @@ public class ManageAccountActivity extends XmppActivity {
accountListView.clearChoices();
accountListView.requestLayout();
accountListView.post(new Runnable() {
- @Override
- public void run() {
- accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
- }
- });
+ @Override
+ public void run() {
+ accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
+ }
+ });
}
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (resultCode == RESULT_OK) {
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_ANNOUNCE_PGP) {
- announcePgp(selectedAccountForActionMode,null);
+ announcePgp(selectedAccountForActionMode, null);
}
- }
- }
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/ui/MucDetailsActivity.java b/src/eu/siacs/conversations/ui/MucDetailsActivity.java
index ee6709b7..8226e381 100644
--- a/src/eu/siacs/conversations/ui/MucDetailsActivity.java
+++ b/src/eu/siacs/conversations/ui/MucDetailsActivity.java
@@ -11,9 +11,9 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.User;
import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
@@ -62,7 +62,8 @@ public class MucDetailsActivity extends XmppActivity {
String subject = mSubject.getText().toString();
MucOptions options = conversation.getMucOptions();
if (!subject.equals(options.getSubject())) {
- xmppConnectionService.sendConversationSubject(conversation,subject);
+ MessagePacket packet = xmppConnectionService.getMessageGenerator().conferenceSubject(conversation, subject);
+ xmppConnectionService.sendMessagePacket(conversation.getAccount(), packet);
finish();
}
}
@@ -72,11 +73,11 @@ public class MucDetailsActivity extends XmppActivity {
@Override
public void onClick(View v) {
- Intent intent = new Intent(getApplicationContext(),
+ /*Intent intent = new Intent(getApplicationContext(),
ContactsActivity.class);
intent.setAction("invite");
intent.putExtra("uuid",conversation.getUuid());
- startActivity(intent);
+ startActivity(intent);*/
}
};
diff --git a/src/eu/siacs/conversations/ui/OnAccountListChangedListener.java b/src/eu/siacs/conversations/ui/OnAccountListChangedListener.java
deleted file mode 100644
index 98ef445e..00000000
--- a/src/eu/siacs/conversations/ui/OnAccountListChangedListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package eu.siacs.conversations.ui;
-
-public interface OnAccountListChangedListener {
- public void onAccountListChangedListener();
-}
diff --git a/src/eu/siacs/conversations/ui/OnConversationListChangedListener.java b/src/eu/siacs/conversations/ui/OnConversationListChangedListener.java
deleted file mode 100644
index 2a922e21..00000000
--- a/src/eu/siacs/conversations/ui/OnConversationListChangedListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package eu.siacs.conversations.ui;
-
-public interface OnConversationListChangedListener {
- public void onConversationListChanged();
-}
diff --git a/src/eu/siacs/conversations/ui/ShareWithActivity.java b/src/eu/siacs/conversations/ui/ShareWithActivity.java
index 9fe5e500..461aaec4 100644
--- a/src/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -20,7 +20,6 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
@@ -90,7 +89,8 @@ public class ShareWithActivity extends XmppActivity {
Set<Contact> displayedContacts = new HashSet<Contact>();
conversations.removeAllViews();
- List<Conversation> convList = xmppConnectionService.getConversations();
+ List<Conversation> convList = new ArrayList<Conversation>();
+ xmppConnectionService.populateWithOrderedConversations(convList);
Collections.sort(convList, new Comparator<Conversation>() {
@Override
public int compare(Conversation lhs, Conversation rhs) {
diff --git a/src/eu/siacs/conversations/ui/StartConversation.java b/src/eu/siacs/conversations/ui/StartConversation.java
new file mode 100644
index 00000000..c9166c39
--- /dev/null
+++ b/src/eu/siacs/conversations/ui/StartConversation.java
@@ -0,0 +1,548 @@
+package eu.siacs.conversations.ui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.ListFragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.utils.KnownHostsAdapter;
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.utils.Validator;
+
+public class StartConversation extends XmppActivity {
+
+ private Tab mContactsTab;
+ private Tab mConferencesTab;
+ private ViewPager mViewPager;
+
+ private MyListFragment mContactsListFragment = new MyListFragment();
+ private List<ListItem> contacts = new ArrayList<ListItem>();
+ private ArrayAdapter<ListItem> mContactsAdapter;
+
+ private MyListFragment mConferenceListFragment = new MyListFragment();
+ private List<ListItem> conferences = new ArrayList<ListItem>();
+ private ArrayAdapter<ListItem> mConferenceAdapter;
+
+ private List<String> mActivatedAccounts = new ArrayList<String>();
+ private List<String> mKnownHosts;
+ private List<String> mKnownConferenceHosts;
+
+ private EditText mSearchEditText;
+
+ public int conference_context_id;
+ public int contact_context_id;
+
+ private TabListener mTabListener = new TabListener() {
+
+ @Override
+ public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+ return;
+ }
+
+ @Override
+ public void onTabSelected(Tab tab, FragmentTransaction ft) {
+ mViewPager.setCurrentItem(tab.getPosition());
+ onTabChanged();
+ }
+
+ @Override
+ public void onTabReselected(Tab tab, FragmentTransaction ft) {
+ return;
+ }
+ };
+
+ private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ getActionBar().setSelectedNavigationItem(position);
+ onTabChanged();
+ }
+ };
+
+ private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
+
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ mSearchEditText.post(new Runnable() {
+
+ @Override
+ public void run() {
+ mSearchEditText.requestFocus();
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mSearchEditText,
+ InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
+ InputMethodManager.HIDE_IMPLICIT_ONLY);
+ mSearchEditText.setText("");
+ filter(null);
+ return true;
+ }
+ };
+ private TextWatcher mSearchTextWatcher = new TextWatcher() {
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ filter(editable.toString());
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before,
+ int count) {
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_start_conversation);
+ mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager);
+ ActionBar actionBar = getActionBar();
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+
+ mContactsTab = actionBar.newTab().setText(R.string.contacts)
+ .setTabListener(mTabListener);
+ mConferencesTab = actionBar.newTab().setText(R.string.conferences)
+ .setTabListener(mTabListener);
+ actionBar.addTab(mContactsTab);
+ actionBar.addTab(mConferencesTab);
+
+ mViewPager.setOnPageChangeListener(mOnPageChangeListener);
+ mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) {
+
+ @Override
+ public int getCount() {
+ return 2;
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ if (position == 0) {
+ return mContactsListFragment;
+ } else {
+ return mConferenceListFragment;
+ }
+ }
+ });
+
+ mConferenceAdapter = new ListItemAdapter(conferences);
+ mConferenceListFragment.setListAdapter(mConferenceAdapter);
+ mConferenceListFragment.setContextMenu(R.menu.conference_context);
+ mConferenceListFragment.setOnListItemClickListener(new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View arg1,
+ int position, long arg3) {
+ openConversationForBookmark(position);
+ }
+ });
+
+ mContactsAdapter = new ListItemAdapter(contacts);
+ mContactsListFragment.setListAdapter(mContactsAdapter);
+ mContactsListFragment.setContextMenu(R.menu.contact_context);
+ mContactsListFragment
+ .setOnListItemClickListener(new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View arg1,
+ int position, long arg3) {
+ openConversationForContact(position);
+ }
+ });
+
+ }
+
+ protected void openConversationForContact(int position) {
+ Contact contact = (Contact) contacts.get(position);
+ Conversation conversation = xmppConnectionService
+ .findOrCreateConversation(contact.getAccount(),
+ contact.getJid(), false);
+ switchToConversation(conversation);
+ }
+
+ protected void openConversationForContact() {
+ int position = contact_context_id;
+ openConversationForContact(position);
+ }
+
+ protected void openConversationForBookmark() {
+ openConversationForBookmark(conference_context_id);
+ }
+
+ protected void openConversationForBookmark(int position) {
+ Bookmark bookmark = (Bookmark) conferences.get(position);
+ Conversation conversation = xmppConnectionService.findOrCreateConversation(bookmark.getAccount(), bookmark.getJid(), true);
+ conversation.setBookmark(bookmark);
+ if (!bookmark.autojoin()) {
+ bookmark.setAutojoin(true);
+ xmppConnectionService.pushBookmarks(bookmark.getAccount());
+ }
+ switchToConversation(conversation);
+ }
+
+ protected void openDetailsForContact() {
+ int position = contact_context_id;
+ Contact contact = (Contact) contacts.get(position);
+ switchToContactDetails(contact);
+ }
+
+ protected void deleteContact() {
+ int position = contact_context_id;
+ Contact contact = (Contact) contacts.get(position);
+ xmppConnectionService.deleteContactOnServer(contact);
+ filter(mSearchEditText.getText().toString());
+ }
+
+ protected void deleteConference() {
+ int position = contact_context_id;
+ Bookmark bookmark = (Bookmark) conferences.get(position);
+ Account account = bookmark.getAccount();
+ account.getBookmarks().remove(bookmark);
+ xmppConnectionService.pushBookmarks(account);
+ filter(mSearchEditText.getText().toString());
+ }
+
+ protected void showCreateContactDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.create_contact);
+ View dialogView = getLayoutInflater().inflate(
+ R.layout.create_contact_dialog, null);
+ final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
+ final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView
+ .findViewById(R.id.jid);
+ jid.setAdapter(new KnownHostsAdapter(this,
+ android.R.layout.simple_list_item_1, mKnownHosts));
+ populateAccountSpinner(spinner);
+ builder.setView(dialogView);
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.create, null);
+ final AlertDialog dialog = builder.create();
+ dialog.show();
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
+ new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (Validator.isValidJid(jid.getText().toString())) {
+ String accountJid = (String) spinner
+ .getSelectedItem();
+ String contactJid = jid.getText().toString();
+ Account account = xmppConnectionService
+ .findAccountByJid(accountJid);
+ Contact contact = account.getRoster().getContact(
+ contactJid);
+ if (contact.showInRoster()) {
+ jid.setError(getString(R.string.contact_already_exists));
+ } else {
+ xmppConnectionService.createContact(contact);
+ switchToConversation(contact);
+ dialog.dismiss();
+ }
+ } else {
+ jid.setError(getString(R.string.invalid_jid));
+ }
+ }
+ });
+
+ }
+
+ protected void showJoinConferenceDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.join_conference);
+ View dialogView = getLayoutInflater().inflate(
+ R.layout.join_conference_dialog, null);
+ final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
+ final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView
+ .findViewById(R.id.jid);
+ jid.setAdapter(new KnownHostsAdapter(this,
+ android.R.layout.simple_list_item_1, mKnownConferenceHosts));
+ populateAccountSpinner(spinner);
+ final CheckBox bookmarkCheckBox = (CheckBox) dialogView.findViewById(R.id.bookmark);
+ builder.setView(dialogView);
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.join, null);
+ final AlertDialog dialog = builder.create();
+ dialog.show();
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
+ new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (Validator.isValidJid(jid.getText().toString())) {
+ String accountJid = (String) spinner
+ .getSelectedItem();
+ String conferenceJid = jid.getText().toString();
+ Account account = xmppConnectionService
+ .findAccountByJid(accountJid);
+ if (bookmarkCheckBox.isChecked()) {
+ if (account.hasBookmarkFor(conferenceJid)) {
+ jid.setError(getString(R.string.bookmark_already_exists));
+ } else {
+ Bookmark bookmark = new Bookmark(account, conferenceJid);
+ bookmark.setAutojoin(true);
+ account.getBookmarks().add(bookmark);
+ xmppConnectionService.pushBookmarks(account);
+ Conversation conversation = xmppConnectionService
+ .findOrCreateConversation(account,
+ conferenceJid, true);
+ conversation.setBookmark(bookmark);
+ switchToConversation(conversation);
+ }
+ } else {
+ Conversation conversation = xmppConnectionService
+ .findOrCreateConversation(account,
+ conferenceJid, true);
+ switchToConversation(conversation);
+ }
+ } else {
+ jid.setError(getString(R.string.invalid_jid));
+ }
+ }
+ });
+ }
+
+ protected void switchToConversation(Contact contact) {
+ Conversation conversation = xmppConnectionService
+ .findOrCreateConversation(contact.getAccount(),
+ contact.getJid(), false);
+ switchToConversation(conversation);
+ }
+
+ private void populateAccountSpinner(Spinner spinner) {
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, mActivatedAccounts);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.start_conversation, menu);
+ MenuItem menuCreateContact = (MenuItem) menu
+ .findItem(R.id.action_create_contact);
+ MenuItem menuCreateConference = (MenuItem) menu
+ .findItem(R.id.action_join_conference);
+ MenuItem menuSearchView = (MenuItem) menu.findItem(R.id.action_search);
+ menuSearchView.setOnActionExpandListener(mOnActionExpandListener);
+ View mSearchView = menuSearchView.getActionView();
+ mSearchEditText = (EditText) mSearchView
+ .findViewById(R.id.search_field);
+ mSearchEditText.addTextChangedListener(mSearchTextWatcher);
+ if (getActionBar().getSelectedNavigationIndex() == 0) {
+ menuCreateConference.setVisible(false);
+ } else {
+ menuCreateContact.setVisible(false);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_create_contact:
+ showCreateContactDialog();
+ break;
+ case R.id.action_join_conference:
+ showJoinConferenceDialog();
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ void onBackendConnected() {
+ if (mSearchEditText != null) {
+ filter(mSearchEditText.getText().toString());
+ } else {
+ filter(null);
+ }
+ this.mActivatedAccounts.clear();
+ for (Account account : xmppConnectionService.getAccounts()) {
+ if (account.getStatus() != Account.STATUS_DISABLED) {
+ this.mActivatedAccounts.add(account.getJid());
+ }
+ }
+ this.mKnownHosts = xmppConnectionService.getKnownHosts();
+ this.mKnownConferenceHosts = xmppConnectionService
+ .getKnownConferenceHosts();
+ }
+
+ protected void filter(String needle) {
+ this.filterContacts(needle);
+ this.filterConferences(needle);
+ }
+
+ protected void filterContacts(String needle) {
+ this.contacts.clear();
+ for (Account account : xmppConnectionService.getAccounts()) {
+ if (account.getStatus() != Account.STATUS_DISABLED) {
+ for (Contact contact : account.getRoster().getContacts()) {
+ if (contact.showInRoster() && contact.match(needle)) {
+ this.contacts.add(contact);
+ }
+ }
+ }
+ }
+ Collections.sort(this.contacts);
+ mContactsAdapter.notifyDataSetChanged();
+ }
+
+ protected void filterConferences(String needle) {
+ this.conferences.clear();
+ for (Account account : xmppConnectionService.getAccounts()) {
+ if (account.getStatus() != Account.STATUS_DISABLED) {
+ for(Bookmark bookmark : account.getBookmarks()) {
+ if (bookmark.match(needle)) {
+ this.conferences.add(bookmark);
+ }
+ }
+ }
+ }
+ Collections.sort(this.conferences);
+ mConferenceAdapter.notifyDataSetChanged();
+ }
+
+ private void onTabChanged() {
+ invalidateOptionsMenu();
+ }
+
+ private class ListItemAdapter extends ArrayAdapter<ListItem> {
+
+ public ListItemAdapter(List<ListItem> objects) {
+ super(getApplicationContext(), 0, objects);
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ ListItem item = getItem(position);
+ if (view == null) {
+ view = (View) inflater.inflate(R.layout.contact, null);
+ }
+ TextView name = (TextView) view
+ .findViewById(R.id.contact_display_name);
+ TextView jid = (TextView) view.findViewById(R.id.contact_jid);
+ ImageView picture = (ImageView) view
+ .findViewById(R.id.contact_photo);
+
+ jid.setText(item.getJid());
+ name.setText(item.getDisplayName());
+ picture.setImageBitmap(item.getImage(48, getApplicationContext()));
+ return view;
+ }
+
+ }
+
+ public static class MyListFragment extends ListFragment {
+ private AdapterView.OnItemClickListener mOnItemClickListener;
+ private int mResContextMenu;
+
+ public void setContextMenu(int res) {
+ this.mResContextMenu = res;
+ }
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ if (mOnItemClickListener != null) {
+ mOnItemClickListener.onItemClick(l, v, position, id);
+ }
+ }
+
+ public void setOnListItemClickListener(AdapterView.OnItemClickListener l) {
+ this.mOnItemClickListener = l;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ registerForContextMenu(getListView());
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v,
+ ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ StartConversation activity = (StartConversation) getActivity();
+ activity.getMenuInflater().inflate(mResContextMenu,
+ menu);
+ AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
+ if (mResContextMenu == R.menu.conference_context) {
+ activity.conference_context_id = acmi.position;
+ } else {
+ activity.contact_context_id = acmi.position;
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ StartConversation activity = (StartConversation) getActivity();
+ switch (item.getItemId()) {
+ case R.id.context_start_conversation:
+ activity.openConversationForContact();
+ break;
+ case R.id.context_contact_details:
+ activity.openDetailsForContact();
+ break;
+ case R.id.context_delete_contact:
+ activity.deleteContact();
+ break;
+ case R.id.context_join_conference:
+ activity.openConversationForBookmark();
+ break;
+ case R.id.context_delete_conference:
+ activity.deleteConference();
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java
index c95cbfec..217bae55 100644
--- a/src/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/eu/siacs/conversations/ui/XmppActivity.java
@@ -149,6 +149,10 @@ public abstract class XmppActivity extends Activity {
ExceptionHelper.init(getApplicationContext());
}
+ public void switchToConversation(Conversation conversation) {
+ switchToConversation(conversation, null, false);
+ }
+
public void switchToConversation(Conversation conversation, String text,
boolean newTask) {
Intent viewConversationIntent = new Intent(this,
@@ -171,6 +175,14 @@ public abstract class XmppActivity extends Activity {
startActivity(viewConversationIntent);
}
+ public void switchToContactDetails(Contact contact) {
+ Intent intent = new Intent(this, ContactDetailsActivity.class);
+ intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
+ intent.putExtra("account", contact.getAccount().getJid());
+ intent.putExtra("contact", contact.getJid());
+ startActivity(intent);
+ }
+
protected void announcePgp(Account account, final Conversation conversation) {
xmppConnectionService.getPgpEngine().generateSignature(account,
"online", new UiCallback<Account>() {
@@ -191,7 +203,9 @@ public abstract class XmppActivity extends Activity {
public void success(Account account) {
xmppConnectionService.databaseBackend
.updateAccount(account);
- xmppConnectionService.sendPresence(account);
+ xmppConnectionService.sendPresencePacket(account,
+ xmppConnectionService.getPresenceGenerator()
+ .sendPresence(account));
if (conversation != null) {
conversation
.setNextEncryption(Message.ENCRYPTION_PGP);
@@ -221,7 +235,7 @@ public abstract class XmppActivity extends Activity {
});
}
-
+
protected void showAddToRosterDialog(final Conversation conversation) {
String jid = conversation.getContactJid();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -241,7 +255,7 @@ public abstract class XmppActivity extends Activity {
});
builder.create().show();
}
-
+
public void selectPresence(final Conversation conversation,
final OnPresenceSelected listener) {
Contact contact = conversation.getContact();
diff --git a/src/eu/siacs/conversations/utils/KnownHostsAdapter.java b/src/eu/siacs/conversations/utils/KnownHostsAdapter.java
new file mode 100644
index 00000000..a0a223dd
--- /dev/null
+++ b/src/eu/siacs/conversations/utils/KnownHostsAdapter.java
@@ -0,0 +1,69 @@
+package eu.siacs.conversations.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+import android.widget.Filter;
+
+public class KnownHostsAdapter extends ArrayAdapter<String> {
+ private ArrayList<String> domains;
+ private Filter domainFilter = new Filter() {
+
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ if (constraint != null) {
+ ArrayList<String> suggestions = new ArrayList<String>();
+ final String[] split = constraint.toString().split("@");
+ if (split.length == 1) {
+ for (String domain : domains) {
+ suggestions.add(split[0].toLowerCase(Locale.getDefault()) + "@" + domain);
+ }
+ } else if (split.length == 2) {
+ for (String domain : domains) {
+ if (domain.contains(split[1])) {
+ suggestions.add(split[0].toLowerCase(Locale.getDefault()) + "@" + domain);
+ }
+ }
+ } else {
+ return new FilterResults();
+ }
+ FilterResults filterResults = new FilterResults();
+ filterResults.values = suggestions;
+ filterResults.count = suggestions.size();
+ return filterResults;
+ } else {
+ return new FilterResults();
+ }
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint,
+ FilterResults results) {
+ ArrayList<String> filteredList = ((ArrayList<String>) results.values);
+ if (results != null && results.count > 0) {
+ clear();
+ for (String c : filteredList) {
+ add(c);
+ }
+ notifyDataSetChanged();
+ }
+ }
+ };
+
+ public KnownHostsAdapter(Context context, int viewResourceId,
+ List<String> mKnownHosts) {
+ super(context, viewResourceId, mKnownHosts);
+ domains = new ArrayList<String>(mKnownHosts.size());
+ for (String domain : mKnownHosts) {
+ domains.add(new String(domain));
+ }
+ }
+
+ @Override
+ public Filter getFilter() {
+ return domainFilter;
+ }
+} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java
index 529d2b4c..ede43830 100644
--- a/src/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/eu/siacs/conversations/utils/UIHelper.java
@@ -13,11 +13,11 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions.User;
import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.ui.ManageAccountActivity;
-
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
@@ -45,13 +45,12 @@ import android.text.Html;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.LinearLayout;
import android.widget.QuickContactBadge;
import android.widget.TextView;
public class UIHelper {
private static final int BG_COLOR = 0xFF181818;
- private static final int FG_COLOR = 0xFFE5E5E5;
+ private static final int FG_COLOR = 0xFFFAFAFA;
private static final int TRANSPARENT = 0x00000000;
private static final int DATE_NO_YEAR_FLAGS = DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NO_YEAR | DateUtils.FORMAT_ABBREV_ALL;
@@ -69,7 +68,7 @@ public class UIHelper {
} else if (difference < 60 * 15) {
return context.getString(R.string.minutes_ago,
Math.round(difference / 60.0));
- } else if (today(date)) {
+ } else if (today(date) || difference < 6 * 60 * 60) {
java.text.DateFormat df = DateFormat.getTimeFormat(context);
return df.format(date);
} else {
@@ -120,8 +119,9 @@ public class UIHelper {
}
private static int getNameColor(String name) {
- int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713,
- 0xFFe92727 };
+ /*int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713,
+ 0xFFe92727 };*/
+ int holoColors[] = {0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, 0xFF795548, 0xFF607d8b};
return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)];
}
@@ -165,7 +165,7 @@ public class UIHelper {
if (names.length > 4) {
letters[3] = "\u2026"; // Unicode ellipsis
- colors[3] = 0xFF444444;
+ colors[3] = 0xFF202020;
}
}
@@ -491,7 +491,7 @@ public class UIHelper {
public static AlertDialog getVerifyFingerprintDialog(
final ConversationActivity activity,
- final Conversation conversation, final LinearLayout msg) {
+ final Conversation conversation, final View msg) {
final Contact contact = conversation.getContact();
final Account account = conversation.getAccount();
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index b2829c6e..72018394 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -18,7 +18,6 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
@@ -793,20 +792,10 @@ public class XmppConnection implements Runnable {
this.sendPacket(packet, null);
}
- public void sendMessagePacket(MessagePacket packet,
- OnMessagePacketReceived callback) {
- this.sendPacket(packet, callback);
- }
-
public void sendPresencePacket(PresencePacket packet) {
this.sendPacket(packet, null);
}
-
- public void sendPresencePacket(PresencePacket packet,
- OnPresencePacketReceived callback) {
- this.sendPacket(packet, callback);
- }
-
+
private synchronized void sendPacket(final AbstractStanza packet,
PacketReceived callback) {
// TODO dont increment stanza count if packet = request packet or ack;
@@ -926,14 +915,10 @@ public class XmppConnection implements Runnable {
public List<String> findDiscoItemsByFeature(String feature) {
List<String> items = new ArrayList<String>();
- Iterator<Entry<String, List<String>>> it = this.disco.entrySet()
- .iterator();
- while (it.hasNext()) {
- Entry<String, List<String>> pairs = it.next();
- if (pairs.getValue().contains(feature)) {
- items.add(pairs.getKey());
+ for (Entry<String, List<String>> cursor : disco.entrySet()) {
+ if (cursor.getValue().contains(feature)) {
+ items.add(cursor.getKey());
}
- it.remove();
}
return items;
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index 1f287194..f1a0373c 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -83,7 +83,7 @@ public class JingleConnection {
sendSuccess();
if (acceptedAutomatically) {
message.markUnread();
- JingleConnection.this.mXmppConnectionService.updateUi(message.getConversation(), true);
+ JingleConnection.this.mXmppConnectionService.notifyUi(message.getConversation(), true);
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
@@ -277,7 +277,7 @@ public class JingleConnection {
} else {
message.markUnread();
Log.d("xmppService","not auto accepting new file offer with size: "+size+" allowed size:"+this.mJingleConnectionManager.getAutoAcceptFileSize());
- this.mXmppConnectionService.updateUi(conversation, true);
+ this.mXmppConnectionService.notifyUi(conversation, true);
}
this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message,false);
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
@@ -507,10 +507,8 @@ public class JingleConnection {
private JingleSocks5Transport chooseConnection() {
JingleSocks5Transport connection = null;
- Iterator<Entry<String, JingleSocks5Transport>> it = this.connections.entrySet().iterator();
- while (it.hasNext()) {
- Entry<String, JingleSocks5Transport> pairs = it.next();
- JingleSocks5Transport currentConnection = pairs.getValue();
+ for (Entry<String, JingleSocks5Transport> cursor : connections.entrySet()) {
+ JingleSocks5Transport currentConnection = cursor.getValue();
//Log.d("xmppService","comparing candidate: "+currentConnection.getCandidate().toString());
if (currentConnection.isEstablished()&&(currentConnection.getCandidate().isUsedByCounterpart()||(!currentConnection.getCandidate().isOurs()))) {
//Log.d("xmppService","is usable");
@@ -533,7 +531,6 @@ public class JingleConnection {
}
}
}
- it.remove();
}
return connection;
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
index d4af624a..f01d7fa9 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
@@ -2,12 +2,11 @@ package eu.siacs.conversations.xmpp.jingle;
import java.math.BigInteger;
import java.security.SecureRandom;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-
+import java.util.concurrent.CopyOnWriteArrayList;
+import android.annotation.SuppressLint;
import android.util.Log;
-
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
@@ -20,10 +19,11 @@ public class JingleConnectionManager {
private XmppConnectionService xmppConnectionService;
- private List<JingleConnection> connections = new ArrayList<JingleConnection>();
+ private List<JingleConnection> connections = new CopyOnWriteArrayList<JingleConnection>();
private HashMap<String, JingleCandidate> primaryCandidates = new HashMap<String, JingleCandidate>();
+ @SuppressLint("TrulyRandom")
private SecureRandom random = new SecureRandom();
public JingleConnectionManager(XmppConnectionService service) {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
index f9de6a6a..d2c84325 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
@@ -5,7 +5,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
-import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;