added max history age (default 1w). automatically sort newly added mam messages
This commit is contained in:
parent
4a94389f05
commit
0ab530932a
|
@ -22,6 +22,8 @@ public final class Config {
|
||||||
|
|
||||||
public static final boolean NO_PROXY_LOOKUP = false; //useful to debug ibb
|
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() {
|
private Config() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,4 @@ public abstract class AbstractEntity {
|
||||||
public boolean equals(AbstractEntity entity) {
|
public boolean equals(AbstractEntity entity) {
|
||||||
return this.getUuid().equals(entity.getUuid());
|
return this.getUuid().equals(entity.getUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import org.json.JSONObject;
|
||||||
|
|
||||||
import java.security.interfaces.DSAPublicKey;
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
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));
|
this.setAttribute(ATTRIBUTE_LAST_MESSAGE_RECEIVED, String.valueOf(value));
|
||||||
|
return (value - before > 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastMessageReceived() {
|
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) {
|
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 class Smp {
|
||||||
public static final int STATUS_NONE = 0;
|
public static final int STATUS_NONE = 0;
|
||||||
public static final int STATUS_CONTACT_REQUESTED = 1;
|
public static final int STATUS_CONTACT_REQUESTED = 1;
|
||||||
|
|
|
@ -493,6 +493,11 @@ public class Message extends AbstractEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void untie() {
|
||||||
|
this.mNextMessage = null;
|
||||||
|
this.mPreviousMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
public class ImageParams {
|
public class ImageParams {
|
||||||
public URL url;
|
public URL url;
|
||||||
public long size = 0;
|
public long size = 0;
|
||||||
|
|
|
@ -549,8 +549,11 @@ public class MessageParser extends AbstractParser implements
|
||||||
}
|
}
|
||||||
Conversation conversation = message.getConversation();
|
Conversation conversation = message.getConversation();
|
||||||
conversation.add(message);
|
conversation.add(message);
|
||||||
conversation.setLastMessageReceived(System.currentTimeMillis());
|
if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().advancedStreamFeaturesLoaded()) {
|
||||||
mXmppConnectionService.updateConversation(conversation);
|
if (conversation.setLastMessageReceived(System.currentTimeMillis())) {
|
||||||
|
mXmppConnectionService.updateConversation(conversation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (message.getStatus() == Message.STATUS_RECEIVED
|
if (message.getStatus() == Message.STATUS_RECEIVED
|
||||||
&& conversation.getOtrSession() != null
|
&& conversation.getOtrSession() != null
|
||||||
|
|
|
@ -4,16 +4,18 @@ import android.util.Log;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
|
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
|
||||||
public class MessageArchiveService {
|
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
private final XmppConnectionService mXmppConnectionService;
|
private final XmppConnectionService mXmppConnectionService;
|
||||||
|
|
||||||
|
@ -28,18 +30,31 @@ public class MessageArchiveService {
|
||||||
final Account account = conversation.getAccount();
|
final Account account = conversation.getAccount();
|
||||||
long start = conversation.getLastMessageReceived();
|
long start = conversation.getLastMessageReceived();
|
||||||
long end = account.getXmppConnection().getLastSessionEstablished();
|
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);
|
final Query query = new Query(conversation, start, end);
|
||||||
this.queries.add(query);
|
this.queries.add(query);
|
||||||
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
|
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
|
||||||
this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
|
this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
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) {
|
public void processFin(Element fin) {
|
||||||
if (fin == null) {
|
if (fin == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -48,27 +63,26 @@ public class MessageArchiveService {
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.d(Config.LOGTAG,"fin "+fin.toString());
|
|
||||||
boolean complete = fin.getAttributeAsBoolean("complete");
|
boolean complete = fin.getAttributeAsBoolean("complete");
|
||||||
Element set = fin.findChild("set","http://jabber.org/protocol/rsm");
|
Element set = fin.findChild("set","http://jabber.org/protocol/rsm");
|
||||||
Element last = set == null ? null : set.findChild("last");
|
Element last = set == null ? null : set.findChild("last");
|
||||||
if (complete || last == null) {
|
if (complete || last == null) {
|
||||||
Log.d(Config.LOGTAG,"completed mam query for "+query.getWith().toString());
|
final Account account = query.getConversation().getAccount();
|
||||||
synchronized (this.queries) {
|
Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": completed mam query for "+query.getWith().toString());
|
||||||
this.queries.remove(query);
|
this.finalizeQuery(query);
|
||||||
}
|
|
||||||
} else {
|
} 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);
|
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(nextQuery);
|
||||||
synchronized (this.queries) {
|
synchronized (this.queries) {
|
||||||
this.queries.remove(query);
|
this.queries.remove(query);
|
||||||
this.queries.add(nextQuery);
|
this.queries.add(nextQuery);
|
||||||
}
|
}
|
||||||
Log.d(Config.LOGTAG,packet.toString());
|
|
||||||
this.mXmppConnectionService.sendIqPacket(query.getConversation().getAccount(),packet,new OnIqPacketReceived() {
|
this.mXmppConnectionService.sendIqPacket(query.getConversation().getAccount(),packet,new OnIqPacketReceived() {
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
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 {
|
public class Query {
|
||||||
private long start;
|
private long start;
|
||||||
private long end;
|
private long end;
|
||||||
|
|
|
@ -73,7 +73,7 @@ import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
|
||||||
import eu.siacs.conversations.utils.PRNGFixes;
|
import eu.siacs.conversations.utils.PRNGFixes;
|
||||||
import eu.siacs.conversations.utils.PhoneHelper;
|
import eu.siacs.conversations.utils.PhoneHelper;
|
||||||
import eu.siacs.conversations.xml.Element;
|
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.OnBindListener;
|
||||||
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
||||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
|
@ -205,12 +205,7 @@ public class XmppConnectionService extends Service {
|
||||||
getNotificationService().updateErrorNotification();
|
getNotificationService().updateErrorNotification();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private OnAdvancedStreamFeaturesAvailable onAdvancedStreamFeaturesAvailable = new OnAdvancedStreamFeaturesAvailable() {
|
|
||||||
@Override
|
|
||||||
public void onAdvancedStreamFeaturesAvailable(Account account) {
|
|
||||||
queryMessagesFromArchive(account);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private int accountChangedListenerCount = 0;
|
private int accountChangedListenerCount = 0;
|
||||||
private OnRosterUpdate mOnRosterUpdate = null;
|
private OnRosterUpdate mOnRosterUpdate = null;
|
||||||
private int rosterChangedListenerCount = 0;
|
private int rosterChangedListenerCount = 0;
|
||||||
|
@ -592,7 +587,7 @@ public class XmppConnectionService extends Service {
|
||||||
connection.setOnJinglePacketReceivedListener(this.jingleListener);
|
connection.setOnJinglePacketReceivedListener(this.jingleListener);
|
||||||
connection.setOnBindListener(this.mOnBindListener);
|
connection.setOnBindListener(this.mOnBindListener);
|
||||||
connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
|
connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
|
||||||
connection.setOnAdvancedStreamFeaturesAvailableListener(this.onAdvancedStreamFeaturesAvailable);
|
connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,6 +1022,7 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
this.databaseBackend.createConversation(conversation);
|
this.databaseBackend.createConversation(conversation);
|
||||||
}
|
}
|
||||||
|
this.mMessageArchiveService.query(conversation);
|
||||||
this.conversations.add(conversation);
|
this.conversations.add(conversation);
|
||||||
updateConversationUi();
|
updateConversationUi();
|
||||||
return conversation;
|
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) {
|
public void joinMuc(Conversation conversation) {
|
||||||
Account account = conversation.getAccount();
|
Account account = conversation.getAccount();
|
||||||
account.pendingConferenceJoins.remove(conversation);
|
account.pendingConferenceJoins.remove(conversation);
|
||||||
|
|
|
@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
|
||||||
public interface OnAdvancedStreamFeaturesAvailable {
|
public interface OnAdvancedStreamFeaturesLoaded {
|
||||||
public void onAdvancedStreamFeaturesAvailable(final Account account);
|
public void onAdvancedStreamFeaturesAvailable(final Account account);
|
||||||
}
|
}
|
|
@ -107,7 +107,7 @@ public class XmppConnection implements Runnable {
|
||||||
private OnMessagePacketReceived messageListener = null;
|
private OnMessagePacketReceived messageListener = null;
|
||||||
private OnStatusChanged statusListener = null;
|
private OnStatusChanged statusListener = null;
|
||||||
private OnBindListener bindListener = null;
|
private OnBindListener bindListener = null;
|
||||||
private OnAdvancedStreamFeaturesAvailable advancedStreamFeaturesAvailableListener = null;
|
private ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
|
||||||
private OnMessageAcknowledged acknowledgedListener = null;
|
private OnMessageAcknowledged acknowledgedListener = null;
|
||||||
private XmppConnectionService mXmppConnectionService = null;
|
private XmppConnectionService mXmppConnectionService = null;
|
||||||
|
|
||||||
|
@ -772,8 +772,8 @@ public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
if (account.getServer().equals(server.toDomainJid())) {
|
if (account.getServer().equals(server.toDomainJid())) {
|
||||||
enableAdvancedStreamFeatures();
|
enableAdvancedStreamFeatures();
|
||||||
if (advancedStreamFeaturesAvailableListener != null) {
|
for(OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
|
||||||
advancedStreamFeaturesAvailableListener.onAdvancedStreamFeaturesAvailable(account);
|
listener.onAdvancedStreamFeaturesAvailable(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -947,8 +947,10 @@ public class XmppConnection implements Runnable {
|
||||||
this.acknowledgedListener = listener;
|
this.acknowledgedListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnAdvancedStreamFeaturesAvailableListener(OnAdvancedStreamFeaturesAvailable listener) {
|
public void addOnAdvancedStreamFeaturesAvailableListener(OnAdvancedStreamFeaturesLoaded listener) {
|
||||||
this.advancedStreamFeaturesAvailableListener = listener;
|
if (!this.advancedStreamFeaturesLoadedListeners.contains(listener)) {
|
||||||
|
this.advancedStreamFeaturesLoadedListeners.add(listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(boolean force) {
|
public void disconnect(boolean force) {
|
||||||
|
@ -1095,6 +1097,10 @@ public class XmppConnection implements Runnable {
|
||||||
return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
|
return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean advancedStreamFeaturesLoaded() {
|
||||||
|
return disco.containsKey(account.getServer().toString());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean rosterVersioning() {
|
public boolean rosterVersioning() {
|
||||||
return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver");
|
return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue