diff options
Diffstat (limited to 'src/main/java/de/pixart')
8 files changed, 156 insertions, 77 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Conversation.java b/src/main/java/de/pixart/messenger/entities/Conversation.java index 15dc844b1..d95894d00 100644 --- a/src/main/java/de/pixart/messenger/entities/Conversation.java +++ b/src/main/java/de/pixart/messenger/entities/Conversation.java @@ -31,6 +31,7 @@ import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.xmpp.chatstate.ChatState; import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; +import de.pixart.messenger.xmpp.mam.MamReference; public class Conversation extends AbstractEntity implements Blockable, Comparable<Conversation> { @@ -363,12 +364,16 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl return this.mFirstMamReference; } - public void setLastClearHistory(long time) { - setAttribute("ATTRIBUTE_LAST_CLEAR_HISTORY", String.valueOf(time)); + public void setLastClearHistory(long time, String reference) { + if (reference != null) { + setAttribute(ATTRIBUTE_LAST_CLEAR_HISTORY, String.valueOf(time) + ":" + reference); + } else { + setAttribute(ATTRIBUTE_LAST_CLEAR_HISTORY, String.valueOf(time)); + } } - public long getLastClearHistory() { - return getLongAttribute("ATTRIBUTE_LAST_CLEAR_HISTORY", 0); + public MamReference getLastClearHistory() { + return MamReference.fromAttribute(getAttribute(ATTRIBUTE_LAST_CLEAR_HISTORY)); } public List<Jid> getAcceptedCryptoTargets() { @@ -482,11 +487,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl if (this.messages.size() == 0) { Message message = new Message(this, "", Message.ENCRYPTION_NONE); message.setType(Message.TYPE_STATUS); - message.setTime(Math.max(getCreated(), getLastClearHistory())); + message.setTime(Math.max(getCreated(), getLastClearHistory().getTimestamp())); return message; } else { - Message message = this.messages.get(this.messages.size() - 1); - return message; + return this.messages.get(this.messages.size() - 1); } } @@ -854,19 +858,19 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl } } - public long getLastMessageTransmitted() { - final long last_clear = getLastClearHistory(); - long last_received = 0; + public MamReference getLastMessageTransmitted() { + final MamReference lastClear = getLastClearHistory(); + MamReference lastReceived = new MamReference(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 || message.isCarbon()) { - last_received = message.getTimeSent(); + lastReceived = new MamReference(message.getTimeSent(),message.getServerMsgId()); break; } } } - return Math.max(last_clear, last_received); + return MamReference.max(lastClear,lastReceived); } public void setMutedTill(long value) { diff --git a/src/main/java/de/pixart/messenger/generator/IqGenerator.java b/src/main/java/de/pixart/messenger/generator/IqGenerator.java index 301f4d178..927d5d07c 100644 --- a/src/main/java/de/pixart/messenger/generator/IqGenerator.java +++ b/src/main/java/de/pixart/messenger/generator/IqGenerator.java @@ -246,7 +246,9 @@ public class IqGenerator extends AbstractGenerator { } else if (mam.getWith() != null) { data.put("with", mam.getWith().toString()); } - data.put("start", getTimestamp(mam.getStart())); + if (mam.getStart() != 0) { + data.put("start", getTimestamp(mam.getStart())); + } data.put("end", getTimestamp(mam.getEnd())); data.submit(); query.addChild(data); diff --git a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java index d6e45f5fe..ddf516f93 100644 --- a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java +++ b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java @@ -10,7 +10,6 @@ import android.database.sqlite.SQLiteOpenHelper; import android.os.Environment; import android.util.Base64; import android.util.Log; -import android.util.Pair; import org.json.JSONException; import org.json.JSONObject; @@ -51,6 +50,7 @@ import de.pixart.messenger.entities.Roster; import de.pixart.messenger.entities.ServiceDiscoveryResult; import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; +import de.pixart.messenger.xmpp.mam.MamReference; public class DatabaseBackend extends SQLiteOpenHelper { @@ -841,7 +841,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { return db.delete(Message.TABLENAME, where, whereArgs) > 0; } - public Pair<Long, String> getLastMessageReceived(Account account) { + public MamReference getLastMessageReceived(Account account) { Cursor cursor = null; try { SQLiteDatabase db = this.getReadableDatabase(); @@ -852,7 +852,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { return null; } else { cursor.moveToFirst(); - return new Pair<>(cursor.getLong(0), cursor.getString(1)); + return new MamReference(cursor.getLong(0), cursor.getString(1)); } } catch (Exception e) { return null; @@ -877,23 +877,23 @@ public class DatabaseBackend extends SQLiteOpenHelper { return time; } - public Pair<Long, String> getLastClearDate(Account account) { + public MamReference getLastClearDate(Account account) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {Conversation.ATTRIBUTES}; String selection = Conversation.ACCOUNT + "=?"; String[] args = {account.getUuid()}; Cursor cursor = db.query(Conversation.TABLENAME, columns, selection, args, null, null, null); - long maxClearDate = 0; + MamReference maxClearDate = new MamReference(0); while (cursor.moveToNext()) { try { - final JSONObject jsonObject = new JSONObject(cursor.getString(0)); - maxClearDate = Math.max(maxClearDate, jsonObject.getLong(Conversation.ATTRIBUTE_LAST_CLEAR_HISTORY)); + final JSONObject o = new JSONObject(cursor.getString(0)); + maxClearDate = MamReference.max(maxClearDate, MamReference.fromAttribute(o.getString(Conversation.ATTRIBUTE_LAST_CLEAR_HISTORY))); } catch (Exception e) { //ignored } } cursor.close(); - return new Pair<>(maxClearDate, null); + return maxClearDate; } private Cursor getCursorForSession(Account account, AxolotlAddress contact) { diff --git a/src/main/java/de/pixart/messenger/services/MessageArchiveService.java b/src/main/java/de/pixart/messenger/services/MessageArchiveService.java index 5a5b0e9a1..e90bb8d07 100644 --- a/src/main/java/de/pixart/messenger/services/MessageArchiveService.java +++ b/src/main/java/de/pixart/messenger/services/MessageArchiveService.java @@ -1,7 +1,6 @@ package de.pixart.messenger.services; import android.util.Log; -import android.util.Pair; import java.math.BigInteger; import java.util.ArrayList; @@ -19,6 +18,7 @@ import de.pixart.messenger.xml.Element; import de.pixart.messenger.xmpp.OnAdvancedStreamFeaturesLoaded; import de.pixart.messenger.xmpp.OnIqPacketReceived; import de.pixart.messenger.xmpp.jid.Jid; +import de.pixart.messenger.xmpp.mam.MamReference; import de.pixart.messenger.xmpp.stanzas.IqPacket; public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { @@ -46,34 +46,26 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } - final Pair<Long, String> lastMessageReceived = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); - final Pair<Long, String> lastClearDate = mXmppConnectionService.databaseBackend.getLastClearDate(account); - long startCatchup; - final String reference; - if (lastMessageReceived != null && lastMessageReceived.first >= lastClearDate.first) { - startCatchup = lastMessageReceived.first; - reference = lastMessageReceived.second; - } else { - startCatchup = lastClearDate.first; - reference = null; - } - startCatchup = Math.max(startCatchup,mXmppConnectionService.getAutomaticMessageDeletionDate()); + MamReference mamReference = MamReference.max( + mXmppConnectionService.databaseBackend.getLastMessageReceived(account), + mXmppConnectionService.databaseBackend.getLastClearDate(account) + ); + mamReference = MamReference.max(mamReference, mXmppConnectionService.getAutomaticMessageDeletionDate()); long endCatchup = account.getXmppConnection().getLastSessionEstablished(); final Query query; - if (startCatchup == 0) { + if (mamReference.getTimestamp() == 0) { return; - } else if (endCatchup - startCatchup >= Config.MAM_MAX_CATCHUP) { - startCatchup = endCatchup - Config.MAM_MAX_CATCHUP; + } else if (endCatchup - mamReference.getTimestamp() >= Config.MAM_MAX_CATCHUP) { + long startCatchup = endCatchup - Config.MAM_MAX_CATCHUP; List<Conversation> conversations = mXmppConnectionService.getConversations(); for (Conversation conversation : conversations) { - if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account && startCatchup > conversation.getLastMessageTransmitted()) { + if (conversation.getMode() == Conversation.MODE_SINGLE && conversation.getAccount() == account && startCatchup > conversation.getLastMessageTransmitted().getTimestamp()) { this.query(conversation, startCatchup, true); } } - query = new Query(account, startCatchup, endCatchup); + query = new Query(account, new MamReference(startCatchup), endCatchup); } else { - query = new Query(account, startCatchup, endCatchup); - query.reference = reference; + query = new Query(account, mamReference, endCatchup); } synchronized (this.queries) { this.queries.add(query); @@ -82,9 +74,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } public void catchupMUC(final Conversation conversation) { - if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) { + if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) { query(conversation, - 0, + new MamReference(0), System.currentTimeMillis(), true); } else { @@ -96,9 +88,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } public Query query(final Conversation conversation) { - if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) { + if (conversation.getLastMessageTransmitted().getTimestamp() < 0 && conversation.countMessages() == 0) { return query(conversation, - 0, + new MamReference(0), System.currentTimeMillis(), false); } else { @@ -113,22 +105,27 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { return this.query(conversation, conversation.getLastMessageTransmitted(), end, allowCatchup); } - public Query query(Conversation conversation, long start, long end, boolean allowCatchup) { + public Query query(Conversation conversation, MamReference start, long end, boolean allowCatchup) { synchronized (this.queries) { final Query query; - final long startActual = Math.max(start, mXmppConnectionService.getAutomaticMessageDeletionDate()); - if (start == 0) { + final MamReference startActual = MamReference.max(start, mXmppConnectionService.getAutomaticMessageDeletionDate()); + if (start.getTimestamp() == 0) { query = new Query(conversation, startActual, end, false); + query.reference = conversation.getFirstMamReference(); } else { - long maxCatchup = Math.max(startActual, System.currentTimeMillis() - Config.MAM_MAX_CATCHUP); - if (maxCatchup > startActual) { - Query reverseCatchup = new Query(conversation, startActual, maxCatchup, false); - this.queries.add(reverseCatchup); - this.execute(reverseCatchup); + if (allowCatchup) { + MamReference maxCatchup = MamReference.max(startActual, System.currentTimeMillis() - Config.MAM_MAX_CATCHUP); + if (maxCatchup.greaterThan(startActual)) { + Query reverseCatchup = new Query(conversation, startActual, maxCatchup.getTimestamp(), false); + this.queries.add(reverseCatchup); + this.execute(reverseCatchup); + } + query = new Query(conversation, maxCatchup, end, allowCatchup); + } else { + query = new Query(conversation, startActual, end, false); } - query = new Query(conversation, maxCatchup, end, allowCatchup); } - if (start > end) { + if (start.greaterThan(end)) { return null; } this.queries.add(query); @@ -304,27 +301,26 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private boolean catchup = true; - public Query(Conversation conversation, long start, long end) { - this(conversation.getAccount(), start, end); + public Query(Conversation conversation, MamReference start, long end, boolean catchup) { + this(conversation.getAccount(), catchup ? start : start.timeOnly(), end); this.conversation = conversation; - } - - public Query(Conversation conversation, long start, long end, boolean catchup) { - this(conversation, start, end); this.pagingOrder = catchup ? PagingOrder.NORMAL : PagingOrder.REVERSE; this.catchup = catchup; } - public Query(Account account, long start, long end) { + public Query(Account account, MamReference start, long end) { this.account = account; - this.start = start; + if (start.getReference() != null) { + this.reference = start.getReference(); + } else { + this.start = start.getTimestamp(); + } this.end = end; this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); } private Query page(String reference) { - Query query = new Query(this.account, this.start, this.end); - query.reference = reference; + Query query = new Query(this.account, new MamReference(this.start, reference), this.end); query.conversation = conversation; query.totalCount = totalCount; query.actualCount = actualCount; @@ -444,8 +440,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { builder.append(getWith().toString()); } } - builder.append(", start="); - builder.append(AbstractGenerator.getTimestamp(this.start)); + if (this.start != 0) { + builder.append(", start="); + builder.append(AbstractGenerator.getTimestamp(this.start)); + } builder.append(", end="); builder.append(AbstractGenerator.getTimestamp(this.end)); builder.append(", order="+pagingOrder.toString()); diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 7bbc9aa78..f8842953d 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -140,6 +140,7 @@ import de.pixart.messenger.xmpp.jid.Jid; import de.pixart.messenger.xmpp.jingle.JingleConnectionManager; import de.pixart.messenger.xmpp.jingle.OnJinglePacketReceived; import de.pixart.messenger.xmpp.jingle.stanzas.JinglePacket; +import de.pixart.messenger.xmpp.mam.MamReference; import de.pixart.messenger.xmpp.pep.Avatar; import de.pixart.messenger.xmpp.stanzas.IqPacket; import de.pixart.messenger.xmpp.stanzas.MessagePacket; @@ -1754,10 +1755,10 @@ public class XmppConnectionService extends Service { callback.onMoreMessagesLoaded(messages.size(), conversation); } else if (conversation.hasMessagesLeftOnServer() && account.isOnlineAndConnected() - && conversation.getLastClearHistory() == 0) { + && conversation.getLastClearHistory().getTimestamp() == 0) { if ((conversation.getMode() == Conversation.MODE_SINGLE && account.getXmppConnection().getFeatures().mam()) || (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().mamSupport())) { - MessageArchiveService.Query query = getMessageArchiveService().query(conversation, 0, timestamp, false); + MessageArchiveService.Query query = getMessageArchiveService().query(conversation, new MamReference(0), timestamp, false); if (query != null) { query.setCallback(callback); callback.informUser(R.string.fetching_history_from_server); @@ -2417,7 +2418,7 @@ public class XmppConnectionService extends Service { x.addChild("history").setAttribute("maxchars", "0"); } else { // Fallback to muc history - x.addChild("history").setAttribute("since", PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted())); + x.addChild("history").setAttribute("since", PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted().getTimestamp())); } sendPresencePacket(account, packet); if (onConferenceJoined != null) { @@ -3836,15 +3837,19 @@ public class XmppConnectionService extends Service { } public void clearConversationHistory(final Conversation conversation) { - long clearDate; + final long clearDate; + final String reference; if (conversation.countMessages() > 0) { - clearDate = conversation.getLatestMessage().getTimeSent() + 1000; + Message latestMessage = conversation.getLatestMessage(); + clearDate = latestMessage.getTimeSent() + 1000; + reference = latestMessage.getServerMsgId(); } else { clearDate = System.currentTimeMillis(); + reference = null; } conversation.clearMessages(); conversation.setHasMessagesLeftOnServer(false); //avoid messages getting loaded through mam - conversation.setLastClearHistory(clearDate); + conversation.setLastClearHistory(clearDate, reference); Runnable runnable = new Runnable() { @Override public void run() { diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 342e52451..084c27a99 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -1354,7 +1354,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private boolean showLoadMoreMessages(final Conversation c) { final boolean mam = hasMamSupport(c); final MessageArchiveService service = activity.xmppConnectionService.getMessageArchiveService(); - return mam && (c.getLastClearHistory() != 0 || (c.countMessages() == 0 && c.messagesLoaded.get() && c.hasMessagesLeftOnServer() && !service.queryInProgress(c))); + return mam && (c.getLastClearHistory().getTimestamp() != 0 || (c.countMessages() == 0 && c.messagesLoaded.get() && c.hasMessagesLeftOnServer() && !service.queryInProgress(c))); } private boolean hasMamSupport(final Conversation c) { diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java index a2c837ea0..c451015cf 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java @@ -77,6 +77,7 @@ import de.pixart.messenger.utils.CryptoHelper; import de.pixart.messenger.utils.GeoHelper; import de.pixart.messenger.utils.Patterns; import de.pixart.messenger.utils.UIHelper; +import de.pixart.messenger.xmpp.mam.MamReference; import ezvcard.Ezvcard; import ezvcard.VCard; import nl.changer.audiowife.AudioWife; @@ -745,16 +746,16 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void loadMoreMessages(Conversation conversation) { - conversation.setLastClearHistory(0); + conversation.setLastClearHistory(0, null); activity.xmppConnectionService.updateConversation(conversation); conversation.setHasMessagesLeftOnServer(true); conversation.setFirstMamReference(null); - long timestamp = conversation.getLastMessageTransmitted(); + long timestamp = conversation.getLastMessageTransmitted().getTimestamp(); if (timestamp == 0) { timestamp = System.currentTimeMillis(); } conversation.messagesLoaded.set(true); - MessageArchiveService.Query query = activity.xmppConnectionService.getMessageArchiveService().query(conversation, 0, timestamp, false); + MessageArchiveService.Query query = activity.xmppConnectionService.getMessageArchiveService().query(conversation, new MamReference(0), timestamp, false); if (query != null) { Toast.makeText(activity, R.string.fetching_history_from_server, Toast.LENGTH_LONG).show(); } else { diff --git a/src/main/java/de/pixart/messenger/xmpp/mam/MamReference.java b/src/main/java/de/pixart/messenger/xmpp/mam/MamReference.java new file mode 100644 index 000000000..788e04889 --- /dev/null +++ b/src/main/java/de/pixart/messenger/xmpp/mam/MamReference.java @@ -0,0 +1,69 @@ +package de.pixart.messenger.xmpp.mam; + +public class MamReference { + + private final long timestamp; + private final String reference; + + public MamReference(long timestamp) { + this.timestamp = timestamp; + this.reference = null; + } + + public MamReference(long timestamp, String reference) { + this.timestamp = timestamp; + this.reference = reference; + } + + public long getTimestamp() { + return timestamp; + } + + public String getReference() { + return reference; + } + + public boolean greaterThan(MamReference b) { + return timestamp > b.getTimestamp(); + } + + public boolean greaterThan(long b) { + return timestamp > b; + } + + public static MamReference max(MamReference a, MamReference b) { + if (a != null && b != null) { + return a.timestamp > b.timestamp ? a : b; + } else if (a != null) { + return a; + } else { + return b; + } + } + + public static MamReference max(MamReference a, long b) { + return max(a,new MamReference(b)); + } + + public static MamReference fromAttribute(String attr) { + if (attr == null) { + return new MamReference(0); + } else { + String[] attrs = attr.split(":"); + try { + long timestamp = Long.parseLong(attrs[0]); + if (attrs.length >= 2) { + return new MamReference(timestamp,attrs[1]); + } else { + return new MamReference(timestamp); + } + } catch (Exception e) { + return new MamReference(0); + } + } + } + + public MamReference timeOnly() { + return reference == null ? this : new MamReference(timestamp); + } +}
\ No newline at end of file |