Include source message in a forked-off thread "show only" view

Stephen Paul Weber created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java   | 23 
src/main/java/eu/siacs/conversations/entities/Message.java        | 12 
src/main/java/eu/siacs/conversations/parser/MessageParser.java    |  3 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java |  8 
4 files changed, 36 insertions(+), 10 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -573,15 +573,32 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
         return reactionEmoji;
     }
 
+    public long loadMoreTimestamp() {
+        if (messages.size() < 1) return 0;
+        if (getLockThread() && messages.size() > 5000) return 0;
+
+        if (messages.get(0).getType() == Message.TYPE_STATUS && messages.size() >= 2) {
+            return messages.get(1).getTimeSent();
+        } else {
+            return messages.get(0).getTimeSent();
+        }
+    }
+
     public void populateWithMessages(final List<Message> messages) {
         synchronized (this.messages) {
             messages.clear();
             messages.addAll(this.messages);
         }
-        for (Iterator<Message> iterator = messages.iterator(); iterator.hasNext(); ) {
-            Message m = iterator.next();
-            if (m.wasMergedIntoPrevious() || (getLockThread() && (m.getThread() == null || !m.getThread().getContent().equals(getThread().getContent())))) {
+        Set<String> extraIds = new HashSet<>();
+        for (ListIterator<Message> iterator = messages.listIterator(messages.size()); iterator.hasPrevious(); ) {
+            Message m = iterator.previous();
+            if (m.wasMergedIntoPrevious() || (getLockThread() && !extraIds.contains(m.replyId()) && (m.getThread() == null || !m.getThread().getContent().equals(getThread().getContent())))) {
                 iterator.remove();
+            } else if (getLockThread() && m.getThread() != null) {
+                Element reply = m.getReply();
+                if (reply != null && reply.getAttribute("id") != null) extraIds.add(reply.getAttribute("id"));
+                Element reactions = m.getReactions();
+                if (reactions != null && reactions.getAttribute("id") != null) extraIds.add(reactions.getAttribute("id"));
             }
         }
     }

src/main/java/eu/siacs/conversations/entities/Message.java 🔗

@@ -437,6 +437,18 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
         return null;
     }
 
+    public Element getReply() {
+        if (this.payloads == null) return null;
+
+        for (Element el : this.payloads) {
+            if (el.getName().equals("reply") && el.getNamespace().equals("urn:xmpp:reply:0")) {
+                return el;
+            }
+        }
+
+        return null;
+    }
+
     public String getConversationUuid() {
         return conversationUuid;
     }

src/main/java/eu/siacs/conversations/parser/MessageParser.java 🔗

@@ -668,6 +668,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
                     el.setAttribute("xmlns", "jabber:client");
                     message.addPayload(el);
                 }
+                if (el.getName().equals("reply") && el.getNamespace() != null && el.getNamespace().equals("urn:xmpp:reply:0")) {
+                    message.addPayload(el);
+                }
             }
             if (conversationMultiMode) {
                 message.setMucUser(conversation.getMucOptions().findUserByFullJid(counterpart));

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -295,13 +295,7 @@ public class ConversationFragment extends XmppFragment
                                 && conversation != null
                                 && conversation.messagesLoaded.compareAndSet(true, false)
                                 && messageList.size() > 0) {
-                            long timestamp;
-                            if (messageList.get(0).getType() == Message.TYPE_STATUS
-                                    && messageList.size() >= 2) {
-                                timestamp = messageList.get(1).getTimeSent();
-                            } else {
-                                timestamp = messageList.get(0).getTimeSent();
-                            }
+                            long timestamp = conversation.loadMoreTimestamp();
                             activity.xmppConnectionService.loadMoreMessages(
                                     conversation,
                                     timestamp,