only offer message correction for the very last message

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java   | 15 
src/main/java/eu/siacs/conversations/entities/Message.java        | 15 +
src/main/java/eu/siacs/conversations/parser/MessageParser.java    |  6 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java |  9 
4 files changed, 37 insertions(+), 8 deletions(-)

Detailed changes

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

@@ -227,11 +227,18 @@ public class Conversation extends AbstractEntity implements Blockable {
 		return null;
 	}
 
-	public Message findMessageWithRemoteIdAndCounterpart(String id, Jid counterpart) {
+	public Message findMessageWithRemoteIdAndCounterpart(String id, Jid counterpart, boolean received, boolean carbon) {
 		synchronized (this.messages) {
-			for(Message message : this.messages) {
-				if(id.equals(message.getRemoteMsgId()) && counterpart.equals(message.getCounterpart())) {
-					return message;
+			for(int i = this.messages.size() - 1; i >= 0; --i) {
+				Message message = messages.get(i);
+				if (counterpart.equals(message.getCounterpart())
+						&& ((message.getStatus() == Message.STATUS_RECEIVED) == received)
+						&& (carbon == message.isCarbon() || received) ) {
+					if (id.equals(message.getRemoteMsgId())) {
+						return message;
+					} else {
+						return null;
+					}
 				}
 			}
 		}

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

@@ -428,6 +428,21 @@ public class Message extends AbstractEntity {
 		}
 	}
 
+	public boolean isLastCorrectableMessage() {
+		Message next = next();
+		while(next != null) {
+			if (next.isCorrectable()) {
+				return false;
+			}
+			next = next.next();
+		}
+		return isCorrectable();
+	}
+
+	private boolean isCorrectable() {
+		return getStatus() != STATUS_RECEIVED && !isCarbon();
+	}
+
 	public boolean mergeable(final Message message) {
 		return message != null &&
 				(message.getType() == Message.TYPE_TEXT &&

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

@@ -336,6 +336,7 @@ public class MessageParser extends AbstractParser implements
 			if (isTypeGroupChat) {
 				if (counterpart.getResourcepart().equals(conversation.getMucOptions().getActualNick())) {
 					status = Message.STATUS_SEND_RECEIVED;
+					isCarbon = true; //not really carbon but received from another resource
 					if (mXmppConnectionService.markMessage(conversation, remoteMsgId, status)) {
 						return;
 					} else if (remoteMsgId == null || Config.IGNORE_ID_REWRITE_IN_MUC) {
@@ -395,7 +396,10 @@ public class MessageParser extends AbstractParser implements
 			}
 
 			if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) {
-				Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, counterpart);
+				Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId,
+						counterpart,
+						message.getStatus() == Message.STATUS_RECEIVED,
+						message.isCarbon());
 				if (replacedMessage != null) {
 					final boolean fingerprintsMatch = replacedMessage.getAxolotlFingerprint() == null
 							|| replacedMessage.getAxolotlFingerprint().equals(message.getAxolotlFingerprint());

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

@@ -514,6 +514,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 
 	private void populateContextMenu(ContextMenu menu) {
 		final Message m = this.selectedMessage;
+		Message relevantForCorrection = m;
+		while(relevantForCorrection.mergeable(relevantForCorrection.next())) {
+			relevantForCorrection = relevantForCorrection.next();
+		}
 		if (m.getType() != Message.TYPE_STATUS) {
 			activity.getMenuInflater().inflate(R.menu.message_context, menu);
 			menu.setHeaderTitle(R.string.message_options);
@@ -530,9 +534,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 					&& m.treatAsDownloadable() != Message.Decision.MUST) {
 				copyText.setVisible(true);
 			}
-			if (m.getType() == Message.TYPE_TEXT
-					&& m.getStatus() != Message.STATUS_RECEIVED
-					&& !m.isCarbon()) {
+			if (relevantForCorrection.getType() == Message.TYPE_TEXT
+					&& relevantForCorrection.isLastCorrectableMessage()) {
 				correctMessage.setVisible(true);
 			}
 			if ((m.getType() != Message.TYPE_TEXT