diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index cdc922b22eff26aaeab5c403bb6f44ce3d61e6f8..9119fe2e0b0399042d0a2c7b025dca4c2f014d35 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -486,11 +486,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl for (int i = this.messages.size() - 1; i >= 0; --i) { final Message message = messages.get(i); final Jid mcp = message.getCounterpart(); - if (mcp == null) { + if (mcp == null && counterpart != null) { continue; } - if (mcp.equals(counterpart) || mcp.asBareJid().equals(counterpart)) { - final boolean idMatch = id.equals(message.getRemoteMsgId()) || message.remoteMsgIdMatchInEdit(id) || (getMode() == MODE_MULTI && id.equals(message.getServerMsgId())); + if (counterpart == null || mcp.equals(counterpart) || mcp.asBareJid().equals(counterpart)) { + final boolean idMatch = id.equals(message.getUuid()) || id.equals(message.getRemoteMsgId()) || message.remoteMsgIdMatchInEdit(id) || (getMode() == MODE_MULTI && id.equals(message.getServerMsgId())); if (idMatch) return message; } } @@ -543,19 +543,26 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl return false; } - public Set findOwnReactionsTo(String id) { - Set reactionEmoji = new HashSet<>(); - Element reactions = null; + public Message findMessageReactingTo(String id, Jid reactor) { synchronized (this.messages) { - for (Message message : this.messages) { - if (message.getStatus() < Message.STATUS_SEND) continue; + for (int i = this.messages.size() - 1; i >= 0; --i) { + final Message message = messages.get(i); + if (reactor == null && message.getStatus() < Message.STATUS_SEND) continue; + if (reactor != null && !(message.getCounterpart().equals(reactor) || message.getCounterpart().asBareJid().equals(reactor))) continue; final Element r = message.getReactions(); if (r != null && r.getAttribute("id") != null && id.equals(r.getAttribute("id"))) { - reactions = r; + return message; } } } + return null; + } + + public Set findReactionsTo(String id, Jid reactor) { + Set reactionEmoji = new HashSet<>(); + Message reactM = findMessageReactingTo(id, reactor); + Element reactions = reactM == null ? null : reactM.getReactions(); if (reactions != null) { for (Element el : reactions.getChildren()) { if (el.getName().equals("reaction") && el.getNamespace().equals("urn:xmpp:reactions:0")) { diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 3a0b677bcd7ef0f1657e4e219301c1c0bb88c316..5ec8dfd04f96e08308c3ab44457ddfa2a6458716 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -403,7 +403,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable public Message react(String emoji) { Set emojis = new HashSet<>(); - if (conversation instanceof Conversation) emojis = ((Conversation) conversation).findOwnReactionsTo(replyId()); + if (conversation instanceof Conversation) emojis = ((Conversation) conversation).findReactionsTo(replyId(), null); emojis.add(emoji); final Message m = reply(); m.appendBody(emoji); @@ -418,6 +418,13 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable return m; } + public void setReactions(Element reactions) { + if (this.payloads != null) { + this.payloads.remove(getReactions()); + } + addPayload(reactions); + } + public Element getReactions() { if (this.payloads == null) return null; diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 62bc7484c87e622a8ead3751094dd268d87ce312..75e6a40027062cefe687f5e9d878246eb30111a3 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -441,7 +441,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } } - final LocalizedContent body = packet.getBody(); + LocalizedContent body = packet.getBody(); final Element axolotlEncrypted = packet.findChildEnsureSingle(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); int status; @@ -500,6 +500,28 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } + final Element reactions = packet.findChild("reactions", "urn:xmpp:reactions:0"); + if (body == null && html == null) { + if (reactions != null && reactions.getAttribute("id") != null) { + final Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid()); + if (conversation != null) { + final Message reactionTo = conversation.findMessageWithRemoteIdAndCounterpart(reactions.getAttribute("id"), null); + if (reactionTo != null) { + String bodyS = reactionTo.reply().getBody(); + for (Element el : reactions.getChildren()) { + if (el.getName().equals("reaction") && el.getNamespace().equals("urn:xmpp:reactions:0")) { + bodyS += el.getContent(); + } + } + body = new LocalizedContent(bodyS, "en", 1); + final Message previousReaction = conversation.findMessageReactingTo(reactions.getAttribute("id"), counterpart); +Log.d("WUT", "" + previousReaction + " " + counterpart); + if (previousReaction != null) replacementId = previousReaction.replyId(); + } + } + } + } + if ((body != null || pgpEncrypted != null || (axolotlEncrypted != null && axolotlEncrypted.hasChild("payload")) || !attachments.isEmpty() || html != null) && !isMucStatusMessage) { final boolean conversationIsProbablyMuc = isTypeGroupChat || mucUserElement != null || account.getXmppConnection().getMucServersWithholdAccount().contains(counterpart.getDomain().toEscapedString()); final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.asBareJid(), conversationIsProbablyMuc, false, query, false); @@ -637,6 +659,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0"); + if (reactions != null) message.addPayload(reactions); for (Element el : packet.getChildren()) { if ((el.getName().equals("query") && el.getNamespace().equals("http://jabber.org/protocol/disco#items") && el.getAttribute("node").equals("http://jabber.org/protocol/commands")) || (el.getName().equals("fallback") && el.getNamespace().equals("urn:xmpp:fallback:0"))) { @@ -693,7 +716,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece replacedMessage.setBody(message.getBody()); replacedMessage.putEdited(replacedMessage.getRemoteMsgId(), replacedMessage.getServerMsgId()); replacedMessage.setRemoteMsgId(remoteMsgId); - if (!replaceElement.getName().equals("replace")) { + if (replaceElement != null && !replaceElement.getName().equals("replace")) { mXmppConnectionService.getFileBackend().deleteFile(replacedMessage); mXmppConnectionService.evictPreview(message.getUuid()); replacedMessage.clearPayloads(); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index b83ae0478c608989447ad7385be20f2cfe99522e..43f0079c80b88ad9bf86a463f23a25938f384203 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1490,6 +1490,10 @@ public class ConversationFragment extends XmppFragment correctMessage.setVisible(true); if (!relevantForCorrection.getBody().equals("") && !relevantForCorrection.getBody().equals(" ")) retractMessage.setVisible(true); } + if (relevantForCorrection.getReactions() != null) { + correctMessage.setVisible(false); + retractMessage.setVisible(true); + } if (conversation.getMode() == Conversation.MODE_MULTI && m.getServerMsgId() != null && m.getModerated() == null && conversation.getMucOptions().getSelf().getRole().ranks(MucOptions.Role.MODERATOR) && conversation.getMucOptions().hasFeature("urn:xmpp:message-moderate:0")) { moderateMessage.setVisible(true); } @@ -1575,11 +1579,18 @@ public class ConversationFragment extends XmppFragment } Element reactions = message.getReactions(); if (reactions != null) { + final Message previousReaction = conversation.findMessageReactingTo(reactions.getAttribute("id"), null); + if (previousReaction != null) reactions = previousReaction.getReactions(); for (Element el : reactions.getChildren()) { if (message.getQuoteableBody().endsWith(el.getContent())) { reactions.removeChild(el); } } + message.setReactions(reactions); + if (previousReaction != null) { + previousReaction.setReactions(reactions); + activity.xmppConnectionService.updateMessage(previousReaction); + } } message.setBody(" "); message.putEdited(message.getUuid(), message.getServerMsgId()); diff --git a/src/main/java/eu/siacs/conversations/xml/LocalizedContent.java b/src/main/java/eu/siacs/conversations/xml/LocalizedContent.java index 6fa71e9625e95891a9c868f94b13fff82b5c781e..eb440f51375f31888ea1f30b64d7e594d6e319b8 100644 --- a/src/main/java/eu/siacs/conversations/xml/LocalizedContent.java +++ b/src/main/java/eu/siacs/conversations/xml/LocalizedContent.java @@ -14,7 +14,7 @@ public class LocalizedContent { public final String language; public final int count; - private LocalizedContent(String content, String language, int count) { + public LocalizedContent(String content, String language, int count) { this.content = content; this.language = language; this.count = count;