@@ -69,10 +69,12 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
+import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
+import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
@@ -541,6 +543,29 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return false;
}
+ public Set<String> findOwnReactionsTo(String id) {
+ Set<String> reactionEmoji = new HashSet<>();
+ Element reactions = null;
+ synchronized (this.messages) {
+ for (Message message : this.messages) {
+ if (message.getStatus() < Message.STATUS_SEND) continue;
+
+ final Element r = message.getReactions();
+ if (r != null && r.getAttribute("id") != null && id.equals(r.getAttribute("id"))) {
+ reactions = r;
+ }
+ }
+ }
+ if (reactions != null) {
+ for (Element el : reactions.getChildren()) {
+ if (el.getName().equals("reaction") && el.getNamespace().equals("urn:xmpp:reactions:0")) {
+ reactionEmoji.add(el.getContent());
+ }
+ }
+ }
+ return reactionEmoji;
+ }
+
public void populateWithMessages(final List<Message> messages) {
synchronized (this.messages) {
messages.clear();
@@ -33,6 +33,7 @@ import java.time.Duration;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -380,13 +381,17 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
return values;
}
+ public String replyId() {
+ return conversation.getMode() == Conversation.MODE_MULTI ? getServerMsgId() : getRemoteMsgId();
+ }
+
public Message reply() {
Message m = new Message(conversation, QuoteHelper.quote(MessageUtils.prepareQuote(this)) + "\n", ENCRYPTION_NONE);
m.setThread(getThread());
m.addPayload(
new Element("reply", "urn:xmpp:reply:0")
.setAttribute("to", getCounterpart())
- .setAttribute("id", conversation.getMode() == Conversation.MODE_MULTI ? getServerMsgId() : getRemoteMsgId())
+ .setAttribute("id", replyId())
);
final Element fallback = new Element("fallback", "urn:xmpp:fallback:0").setAttribute("for", "urn:xmpp:reply:0");
fallback.addChild("body", "urn:xmpp:fallback:0")
@@ -396,6 +401,35 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
return m;
}
+ public Message react(String emoji) {
+ Set<String> emojis = new HashSet<>();
+ if (conversation instanceof Conversation) emojis = ((Conversation) conversation).findOwnReactionsTo(replyId());
+ emojis.add(emoji);
+ final Message m = reply();
+ m.appendBody(emoji);
+ final Element fallback = new Element("fallback", "urn:xmpp:fallback:0").setAttribute("for", "urn:xmpp:reactions:0");
+ fallback.addChild("body", "urn:xmpp:fallback:0");
+ m.addPayload(fallback);
+ final Element reactions = new Element("reactions", "urn:xmpp:reactions:0").setAttribute("id", replyId());
+ for (String oneEmoji : emojis) {
+ reactions.addChild("reaction", "urn:xmpp:reactions:0").setContent(oneEmoji);
+ }
+ m.addPayload(reactions);
+ return m;
+ }
+
+ public Element getReactions() {
+ if (this.payloads == null) return null;
+
+ for (Element el : this.payloads) {
+ if (el.getName().equals("reactions") && el.getNamespace().equals("urn:xmpp:reactions:0")) {
+ return el;
+ }
+ }
+
+ return null;
+ }
+
public String getConversationUuid() {
return conversationUuid;
}
@@ -137,6 +137,7 @@ import eu.siacs.conversations.ui.util.ViewUtil;
import eu.siacs.conversations.ui.widget.EditMessage;
import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.Compatibility;
+import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.MessageUtils;
import eu.siacs.conversations.utils.MimeUtils;
@@ -895,8 +896,12 @@ public class ConversationFragment extends XmppFragment
final Message message;
if (conversation.getCorrectingMessage() == null) {
if (conversation.getReplyTo() != null) {
- message = conversation.getReplyTo().reply();
- message.appendBody(body);
+ if (Emoticons.isEmoji(body)) {
+ message = conversation.getReplyTo().react(body);
+ } else {
+ message = conversation.getReplyTo().reply();
+ message.appendBody(body);
+ }
message.setEncryption(conversation.getNextEncryption());
} else {
message = new Message(conversation, body, conversation.getNextEncryption());
@@ -1568,6 +1573,14 @@ public class ConversationFragment extends XmppFragment
while (message.mergeable(message.next())) {
message = message.next();
}
+ Element reactions = message.getReactions();
+ if (reactions != null) {
+ for (Element el : reactions.getChildren()) {
+ if (message.getQuoteableBody().endsWith(el.getContent())) {
+ reactions.removeChild(el);
+ }
+ }
+ }
message.setBody(" ");
message.putEdited(message.getUuid(), message.getServerMsgId());
message.setServerMsgId(null);