@@ -155,6 +155,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
private String axolotlFingerprint = null;
private String errorMessage = null;
private Set<ReadByMarker> 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());
@@ -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<String, Message> getMessageFuzzyIds(Conversation conversation, Collection<String> ids) {
+ final var result = new Hashtable<String, Message>();
+ if (ids.size() < 1) return result;
+ final ArrayList<String> params = new ArrayList<>();
+ final ArrayList<String> template = new ArrayList<>();
+ for (final var id : ids) {
+ template.add("?");
+ }
+ params.addAll(ids);
+ params.addAll(ids);
+ params.addAll(ids);
ArrayList<Message> 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<Message> getMessages(Conversation conversation, int limit, long timestamp) {
@@ -1155,13 +1172,26 @@ public class DatabaseBackend extends SQLiteOpenHelper {
);
}
CursorUtils.upgradeCursorWindowSize(cursor);
+ final Multimap<String, Message> waitingForReplies = HashMultimap.create();
+ final var replyIds = new HashSet<String>();
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;
}
@@ -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<String, Message> getMessageFuzzyIds(Conversation conversation, Collection<String> ids) {
+ return this.databaseBackend.getMessageFuzzyIds(conversation, ids);
}
public void insertWebxdcUpdate(final WebxdcUpdate update) {
@@ -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);
}
}