aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/eu/siacs/conversations/Config.java2
-rw-r--r--src/main/java/eu/siacs/conversations/entities/AbstractEntity.java1
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Conversation.java39
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Message.java5
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java7
-rw-r--r--src/main/java/eu/siacs/conversations/services/MessageArchiveService.java48
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java25
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java (renamed from src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesAvailable.java)2
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java16
9 files changed, 103 insertions, 42 deletions
diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java
index d777e5cc0..e9e73db9e 100644
--- a/src/main/java/eu/siacs/conversations/Config.java
+++ b/src/main/java/eu/siacs/conversations/Config.java
@@ -22,6 +22,8 @@ public final class Config {
public static final boolean NO_PROXY_LOOKUP = false; //useful to debug ibb
+ public static final long MAX_HISTORY_AGE = 7 * 24 * 60 * 60 * 1000;
+
private Config() {
}
diff --git a/src/main/java/eu/siacs/conversations/entities/AbstractEntity.java b/src/main/java/eu/siacs/conversations/entities/AbstractEntity.java
index 92b8a7298..957b0a146 100644
--- a/src/main/java/eu/siacs/conversations/entities/AbstractEntity.java
+++ b/src/main/java/eu/siacs/conversations/entities/AbstractEntity.java
@@ -17,5 +17,4 @@ public abstract class AbstractEntity {
public boolean equals(AbstractEntity entity) {
return this.getUuid().equals(entity.getUuid());
}
-
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 725ed27b6..63f341e72 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -16,6 +16,8 @@ import org.json.JSONObject;
import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
@@ -471,12 +473,25 @@ public class Conversation extends AbstractEntity {
}
}
- public void setLastMessageReceived(long value) {
+ public boolean setLastMessageReceived(long value) {
+ long before = getLastMessageReceived();
this.setAttribute(ATTRIBUTE_LAST_MESSAGE_RECEIVED, String.valueOf(value));
+ return (value - before > 1000);
}
public long getLastMessageReceived() {
- return getLongAttribute(ATTRIBUTE_LAST_MESSAGE_RECEIVED,0);
+ long timestamp = getLongAttribute(ATTRIBUTE_LAST_MESSAGE_RECEIVED,0);
+ if (timestamp == 0) {
+ synchronized (this.messages) {
+ for(int i = this.messages.size() - 1; i >= 0; --i) {
+ Message message = this.messages.get(i);
+ if (message.getStatus() == Message.STATUS_RECEIVED) {
+ return message.getTimeSent();
+ }
+ }
+ }
+ }
+ return timestamp;
}
public void setMutedTill(long value) {
@@ -544,6 +559,26 @@ public class Conversation extends AbstractEntity {
}
}
+ public void sort() {
+ synchronized (this.messages) {
+ for(Message message : this.messages) {
+ message.untie();
+ }
+ Collections.sort(this.messages,new Comparator<Message>() {
+ @Override
+ public int compare(Message left, Message right) {
+ if (left.getTimeSent() < right.getTimeSent()) {
+ return -1;
+ } else if (left.getTimeSent() > right.getTimeSent()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ });
+ }
+ }
+
public class Smp {
public static final int STATUS_NONE = 0;
public static final int STATUS_CONTACT_REQUESTED = 1;
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java
index 47861d06d..1213f66ab 100644
--- a/src/main/java/eu/siacs/conversations/entities/Message.java
+++ b/src/main/java/eu/siacs/conversations/entities/Message.java
@@ -493,6 +493,11 @@ public class Message extends AbstractEntity {
}
}
+ public void untie() {
+ this.mNextMessage = null;
+ this.mPreviousMessage = null;
+ }
+
public class ImageParams {
public URL url;
public long size = 0;
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index b902db510..3714ac904 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -549,8 +549,11 @@ public class MessageParser extends AbstractParser implements
}
Conversation conversation = message.getConversation();
conversation.add(message);
- conversation.setLastMessageReceived(System.currentTimeMillis());
- mXmppConnectionService.updateConversation(conversation);
+ if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().advancedStreamFeaturesLoaded()) {
+ if (conversation.setLastMessageReceived(System.currentTimeMillis())) {
+ mXmppConnectionService.updateConversation(conversation);
+ }
+ }
if (message.getStatus() == Message.STATUS_RECEIVED
&& conversation.getOtrSession() != null
diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
index 4f47cdbe4..c77262cb4 100644
--- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
+++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
@@ -4,16 +4,18 @@ import android.util.Log;
import java.math.BigInteger;
import java.util.HashSet;
+import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-public class MessageArchiveService {
+public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
private final XmppConnectionService mXmppConnectionService;
@@ -28,18 +30,31 @@ public class MessageArchiveService {
final Account account = conversation.getAccount();
long start = conversation.getLastMessageReceived();
long end = account.getXmppConnection().getLastSessionEstablished();
+ if (end - start >= Config.MAX_HISTORY_AGE) {
+ start = end - Config.MAX_HISTORY_AGE;
+ }
final Query query = new Query(conversation, start, end);
this.queries.add(query);
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
- Log.d(Config.LOGTAG, packet.toString());
+ if (packet.getType() == IqPacket.TYPE_ERROR) {
+ finalizeQuery(query);
+ }
}
});
}
}
+ private void finalizeQuery(Query query) {
+ synchronized (this.queries) {
+ this.queries.remove(query);
+ }
+ query.getConversation().sort();
+ this.mXmppConnectionService.updateConversationUi();
+ }
+
public void processFin(Element fin) {
if (fin == null) {
return;
@@ -48,27 +63,26 @@ public class MessageArchiveService {
if (query == null) {
return;
}
- Log.d(Config.LOGTAG,"fin "+fin.toString());
boolean complete = fin.getAttributeAsBoolean("complete");
Element set = fin.findChild("set","http://jabber.org/protocol/rsm");
Element last = set == null ? null : set.findChild("last");
if (complete || last == null) {
- Log.d(Config.LOGTAG,"completed mam query for "+query.getWith().toString());
- synchronized (this.queries) {
- this.queries.remove(query);
- }
+ final Account account = query.getConversation().getAccount();
+ Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": completed mam query for "+query.getWith().toString());
+ this.finalizeQuery(query);
} else {
- Query nextQuery = query.next(last == null ? null : last.getContent());
+ final Query nextQuery = query.next(last == null ? null : last.getContent());
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(nextQuery);
synchronized (this.queries) {
this.queries.remove(query);
this.queries.add(nextQuery);
}
- Log.d(Config.LOGTAG,packet.toString());
this.mXmppConnectionService.sendIqPacket(query.getConversation().getAccount(),packet,new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
- Log.d(Config.LOGTAG,packet.toString());
+ if (packet.getType() == IqPacket.TYPE_ERROR) {
+ finalizeQuery(nextQuery);
+ }
}
});
}
@@ -88,6 +102,20 @@ public class MessageArchiveService {
}
}
+ @Override
+ public void onAdvancedStreamFeaturesAvailable(Account account) {
+ if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().mam()) {
+ List<Conversation> conversations = mXmppConnectionService.getConversations();
+ for (Conversation conversation : conversations) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account) {
+ this.query(conversation);
+ }
+ }
+ } else {
+ Log.d(Config.LOGTAG,"no mam available");
+ }
+ }
+
public class Query {
private long start;
private long end;
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 9d73868c8..3e2c1b8b5 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -73,7 +73,7 @@ import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PRNGFixes;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesAvailable;
+import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.OnBindListener;
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
@@ -205,12 +205,7 @@ public class XmppConnectionService extends Service {
getNotificationService().updateErrorNotification();
}
};
- private OnAdvancedStreamFeaturesAvailable onAdvancedStreamFeaturesAvailable = new OnAdvancedStreamFeaturesAvailable() {
- @Override
- public void onAdvancedStreamFeaturesAvailable(Account account) {
- queryMessagesFromArchive(account);
- }
- };
+
private int accountChangedListenerCount = 0;
private OnRosterUpdate mOnRosterUpdate = null;
private int rosterChangedListenerCount = 0;
@@ -592,7 +587,7 @@ public class XmppConnectionService extends Service {
connection.setOnJinglePacketReceivedListener(this.jingleListener);
connection.setOnBindListener(this.mOnBindListener);
connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
- connection.setOnAdvancedStreamFeaturesAvailableListener(this.onAdvancedStreamFeaturesAvailable);
+ connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService);
return connection;
}
@@ -1027,6 +1022,7 @@ public class XmppConnectionService extends Service {
}
this.databaseBackend.createConversation(conversation);
}
+ this.mMessageArchiveService.query(conversation);
this.conversations.add(conversation);
updateConversationUi();
return conversation;
@@ -1239,19 +1235,6 @@ public class XmppConnectionService extends Service {
}
}
- private void queryMessagesFromArchive(final Account account) {
- if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().mam()) {
- List<Conversation> conversations = getConversations();
- for (Conversation conversation : conversations) {
- if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account) {
- this.mMessageArchiveService.query(conversation);
- }
- }
- } else {
- Log.d(Config.LOGTAG,"no mam available");
- }
- }
-
public void joinMuc(Conversation conversation) {
Account account = conversation.getAccount();
account.pendingConferenceJoins.remove(conversation);
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesAvailable.java b/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java
index a41bce86a..e45eba73e 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesAvailable.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java
@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
import eu.siacs.conversations.entities.Account;
-public interface OnAdvancedStreamFeaturesAvailable {
+public interface OnAdvancedStreamFeaturesLoaded {
public void onAdvancedStreamFeaturesAvailable(final Account account);
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index 0e5d26ed5..af0499c64 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -107,7 +107,7 @@ public class XmppConnection implements Runnable {
private OnMessagePacketReceived messageListener = null;
private OnStatusChanged statusListener = null;
private OnBindListener bindListener = null;
- private OnAdvancedStreamFeaturesAvailable advancedStreamFeaturesAvailableListener = null;
+ private ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
private OnMessageAcknowledged acknowledgedListener = null;
private XmppConnectionService mXmppConnectionService = null;
@@ -772,8 +772,8 @@ public class XmppConnection implements Runnable {
if (account.getServer().equals(server.toDomainJid())) {
enableAdvancedStreamFeatures();
- if (advancedStreamFeaturesAvailableListener != null) {
- advancedStreamFeaturesAvailableListener.onAdvancedStreamFeaturesAvailable(account);
+ for(OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
+ listener.onAdvancedStreamFeaturesAvailable(account);
}
}
}
@@ -947,8 +947,10 @@ public class XmppConnection implements Runnable {
this.acknowledgedListener = listener;
}
- public void setOnAdvancedStreamFeaturesAvailableListener(OnAdvancedStreamFeaturesAvailable listener) {
- this.advancedStreamFeaturesAvailableListener = listener;
+ public void addOnAdvancedStreamFeaturesAvailableListener(OnAdvancedStreamFeaturesLoaded listener) {
+ if (!this.advancedStreamFeaturesLoadedListeners.contains(listener)) {
+ this.advancedStreamFeaturesLoadedListeners.add(listener);
+ }
}
public void disconnect(boolean force) {
@@ -1095,6 +1097,10 @@ public class XmppConnection implements Runnable {
return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
}
+ public boolean advancedStreamFeaturesLoaded() {
+ return disco.containsKey(account.getServer().toString());
+ }
+
public boolean rosterVersioning() {
return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver");
}