diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ad89812746376f096a467dcf9c31230db8323700..54c229d591a98fb2ff48897157a834c0abdf21f1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -155,6 +155,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable private String axolotlFingerprint = null; private String errorMessage = null; private Set readByMarkers = new CopyOnWriteArraySet<>(); + protected Message mInReplyTo = null; private Boolean isGeoUri = null; private Boolean isEmojisOnly = null; @@ -440,6 +441,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable addPayload(fallback); appendBody(body); + setInReplyTo(replyTo); } public Message react(String emoji) { @@ -905,6 +907,14 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable ReadByMarker::getRealJid)); } + public void setInReplyTo(final Message m) { + mInReplyTo = m; + } + + public Message getInReplyTo() { + return mInReplyTo; + } + boolean similar(Message message) { if (!isPrivateMessage() && this.serverMsgId != null && message.getServerMsgId() != null) { return this.serverMsgId.equals(message.getServerMsgId()) || Edit.wasPreviouslyEditedServerMsgId(edits, message.getServerMsgId()); diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 85995c4bf05b54abf9134e9447c00990d455ad66..41b0f91f2a158ddacf79d3dcf0a3bef7c103594e 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -6,6 +6,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.text.TextUtils; import android.os.Environment; import android.os.SystemClock; import android.util.Base64; @@ -35,7 +36,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.Hashtable; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -1097,7 +1100,17 @@ public class DatabaseBackend extends SQLiteOpenHelper { return getMessages(conversations, limit, -1); } - public Message getMessageFuzzyId(Conversation conversation, String id) { + public Map getMessageFuzzyIds(Conversation conversation, Collection ids) { + final var result = new Hashtable(); + if (ids.size() < 1) return result; + final ArrayList params = new ArrayList<>(); + final ArrayList template = new ArrayList<>(); + for (final var id : ids) { + template.add("?"); + } + params.addAll(ids); + params.addAll(ids); + params.addAll(ids); ArrayList list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; @@ -1105,18 +1118,22 @@ public class DatabaseBackend extends SQLiteOpenHelper { "SELECT * FROM " + Message.TABLENAME + " " + "LEFT JOIN cheogram." + Message.TABLENAME + " USING (" + Message.UUID + ")" + - "WHERE " + Message.UUID + "=? OR " + Message.SERVER_MSG_ID + " =? OR " + Message.REMOTE_MSG_ID + " =?", - new String[]{id,id,id} + "WHERE " + Message.UUID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.SERVER_MSG_ID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.REMOTE_MSG_ID + " IN (" + TextUtils.join(",", template) + ")", + params.toArray(new String[0]) ); + while (cursor.moveToNext()) { try { - return Message.fromCursor(cursor, conversation); + final var m = Message.fromCursor(cursor, conversation); + if (ids.contains(m.getUuid())) result.put(m.getUuid(), m); + if (ids.contains(m.getServerMsgId())) result.put(m.getServerMsgId(), m); + if (ids.contains(m.getRemoteMsgId())) result.put(m.getRemoteMsgId(), m); } catch (Exception e) { Log.e(Config.LOGTAG, "unable to restore message"); } } cursor.close(); - return null; + return result; } public ArrayList getMessages(Conversation conversation, int limit, long timestamp) { @@ -1155,13 +1172,26 @@ public class DatabaseBackend extends SQLiteOpenHelper { ); } CursorUtils.upgradeCursorWindowSize(cursor); + final Multimap waitingForReplies = HashMultimap.create(); + final var replyIds = new HashSet(); while (cursor.moveToNext()) { try { - list.add(0, Message.fromCursor(cursor, conversation)); + final var m = Message.fromCursor(cursor, conversation); + final var reply = m.getReply(); + if (reply != null) { + replyIds.add(reply.getAttribute("id")); + waitingForReplies.put(reply.getAttribute("id"), m); + } + list.add(0, m); } catch (Exception e) { Log.e(Config.LOGTAG, "unable to restore message", e); } } + for (final var parent : getMessageFuzzyIds(conversation, replyIds).entrySet()) { + for (final var m : waitingForReplies.get(parent.getKey())) { + m.setInReplyTo(parent.getValue()); + } + } cursor.close(); return list; } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index f9c3ac72ea2a41c0ab0214f45d191946bd05e110..79fcb7eba8cad4d98133a2fbbac0ce39a81237da 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -671,8 +671,8 @@ public class XmppConnectionService extends Service { return this.databaseBackend.getMessage(conversation, uuid); } - public Message getMessageFuzzyId(Conversation conversation, String id) { - return this.databaseBackend.getMessageFuzzyId(conversation, id); + public Map getMessageFuzzyIds(Conversation conversation, Collection ids) { + return this.databaseBackend.getMessageFuzzyIds(conversation, ids); } public void insertWebxdcUpdate(final WebxdcUpdate update) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 02bb00704602b74573500edc24a66e9c8d4ee18f..bea107d6ef61a0bcf374ff10522f1830cd89d7e9 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -2947,9 +2947,9 @@ public class ConversationFragment extends XmppFragment this.binding.textinputSubject.setText(message.getSubject()); this.binding.textinputSubject.setVisibility(View.VISIBLE); } - final var reply = message.getReply(); - if (reply != null) { - setupReply(activity.xmppConnectionService.getMessageFuzzyId(conversation, reply.getAttribute("id"))); + final var replyTo = message.getInReplyTo(); + if (replyTo != null) { + setupReply(replyTo); } }