Detailed changes
@@ -297,6 +297,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
for (int i = messages.size() - 1; i >= 0; --i) {
final Message message = messages.get(i);
if (message.getSubject() != null && !message.isOOb() && (message.getRawBody() == null || message.getRawBody().length() == 0)) continue;
+ if ((message.getRawBody() == null || "".equals(message.getRawBody()) || " ".equals(message.getRawBody())) && message.getReply() != null && message.edited() && message.getHtml() != null) continue;
if (asReaction(message) != null) continue;
if (message.isRead()) {
return first;
@@ -313,6 +314,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
synchronized (this.messages) {
for (final Message message : Lists.reverse(this.messages)) {
if (message.getSubject() != null && !message.isOOb() && (message.getRawBody() == null || message.getRawBody().length() == 0)) continue;
+ if ((message.getRawBody() == null || "".equals(message.getRawBody()) || " ".equals(message.getRawBody())) && message.getReply() != null && message.edited() && message.getHtml() != null) continue;
if (asReaction(message) != null) continue;
if (message.getStatus() == Message.STATUS_RECEIVED) {
final String serverMsgId = message.getServerMsgId();
@@ -714,6 +716,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
thread.first = m;
}
}
+
+ if ((m.getRawBody() == null || "".equals(m.getRawBody()) || " ".equals(m.getRawBody())) && m.getReply() != null && m.edited() && m.getHtml() != null) {
+ iterator.remove();
+ continue;
+ }
+
final var asReaction = asReaction(m);
if (asReaction != null) {
reactions.put(asReaction.first, asReaction.second);
@@ -734,9 +742,16 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
protected Pair<String, Reaction> asReaction(Message m) {
final var reply = m.getReply();
if (reply != null && reply.getAttribute("id") != null) {
+ final String envelopeId;
+ if (m.isCarbon() || m.getStatus() == Message.STATUS_RECEIVED) {
+ envelopeId = m.getRemoteMsgId();
+ } else {
+ envelopeId = m.getUuid();
+ }
+
final var body = m.getBody(true).toString().replaceAll("\\s", "");
if (Emoticons.isEmoji(body)) {
- return new Pair<>(reply.getAttribute("id"), new Reaction(body, null, m.getStatus() <= Message.STATUS_RECEIVED, m.getCounterpart(), m.getTrueCounterpart(), m.getOccupantId()));
+ return new Pair<>(reply.getAttribute("id"), new Reaction(body, null, m.getStatus() <= Message.STATUS_RECEIVED, m.getCounterpart(), m.getTrueCounterpart(), m.getOccupantId(), envelopeId));
} else {
final var html = m.getHtml();
if (html == null) return null;
@@ -758,7 +773,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
if (source != null && source.length() > 0 && source.substring(0, 4).equals("cid:")) {
final Cid cid = BobTransfer.cid(Uri.parse(source));
- return new Pair<>(reply.getAttribute("id"), new Reaction(shortcode, cid, m.getStatus() <= Message.STATUS_RECEIVED, m.getCounterpart(), m.getTrueCounterpart(), m.getOccupantId()));
+ return new Pair<>(reply.getAttribute("id"), new Reaction(shortcode, cid, m.getStatus() <= Message.STATUS_RECEIVED, m.getCounterpart(), m.getTrueCounterpart(), m.getOccupantId(), envelopeId));
}
}
}
@@ -941,6 +956,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
for(final Message message : Lists.reverse(this.messages)) {
if (message.getSubject() != null && !message.isOOb() && (message.getRawBody() == null || message.getRawBody().length() == 0)) continue;
if (asReaction(message) != null) continue;
+ if ((message.getRawBody() == null || "".equals(message.getRawBody()) || " ".equals(message.getRawBody())) && message.getReply() != null && message.edited() && message.getHtml() != null) continue;
return message;
}
@@ -1411,6 +1427,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
for(final Message message : Lists.reverse(this.messages)) {
if (message.getSubject() != null && !message.isOOb() && (message.getRawBody() == null || message.getRawBody().length() == 0)) continue;
if (asReaction(message) != null) continue;
+ if ((message.getRawBody() == null || "".equals(message.getRawBody()) || " ".equals(message.getRawBody())) && message.getReply() != null && message.edited() && message.getHtml() != null) continue;
final boolean muted = xmppConnectionService != null && message.getStatus() == Message.STATUS_RECEIVED && getMode() == Conversation.MODE_MULTI && xmppConnectionService.isMucUserMuted(new MucOptions.User(null, getJid(), message.getOccupantId(), null, null));
if (muted) continue;
if (message.isRead()) {
@@ -1431,6 +1448,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
for (Message message : messages) {
if (message.getSubject() != null && !message.isOOb() && (message.getRawBody() == null || message.getRawBody().length() == 0)) continue;
if (asReaction(message) != null) continue;
+ if ((message.getRawBody() == null || "".equals(message.getRawBody()) || " ".equals(message.getRawBody())) && message.getReply() != null && message.edited() && message.getHtml() != null) continue;
if (message.getStatus() == Message.STATUS_RECEIVED) {
++count;
}
@@ -60,6 +60,7 @@ public class Reaction {
public final Jid trueJid;
public final String occupantId;
public final Cid cid;
+ public final String envelopeId;
public Reaction(
final String reaction,
@@ -67,13 +68,15 @@ public class Reaction {
boolean received,
final Jid from,
final Jid trueJid,
- final String occupantId) {
+ final String occupantId,
+ final String envelopeId) {
this.reaction = reaction;
this.cid = cid;
this.received = received;
this.from = from;
this.trueJid = trueJid;
this.occupantId = occupantId;
+ this.envelopeId = envelopeId;
}
public static String toString(final Collection<Reaction> reactions) {
@@ -97,12 +100,13 @@ public class Reaction {
final boolean received,
final Jid from,
final Jid trueJid,
- final String occupantId) {
+ final String occupantId,
+ final String envelopeId) {
final ImmutableSet.Builder<Reaction> builder = new ImmutableSet.Builder<>();
builder.addAll(Collections2.filter(existing, e -> !occupantId.equals(e.occupantId)));
builder.addAll(
Collections2.transform(
- reactions, r -> new Reaction(r, null, received, from, trueJid, occupantId)));
+ reactions, r -> new Reaction(r, null, received, from, trueJid, occupantId, envelopeId)));
return builder.build();
}
@@ -133,13 +137,14 @@ public class Reaction {
final Collection<Reaction> existing,
final Collection<String> reactions,
final boolean received,
- final Jid from) {
+ final Jid from,
+ final String envelopeId) {
final ImmutableSet.Builder<Reaction> builder = new ImmutableSet.Builder<>();
builder.addAll(
Collections2.filter(existing, e -> !from.asBareJid().equals(e.from.asBareJid())));
builder.addAll(
Collections2.transform(
- reactions, r -> new Reaction(r, null, received, from, null, null)));
+ reactions, r -> new Reaction(r, null, received, from, null, null, envelopeId)));
return builder.build();
}
@@ -1306,7 +1306,8 @@ public class MessageParser extends AbstractParser implements Consumer<im.convers
isReceived,
counterpart,
null,
- occupantId);
+ occupantId,
+ message.getRemoteMsgId());
message.setReactions(combinedReactions);
mXmppConnectionService.updateMessage(message, false);
} else {
@@ -1330,7 +1331,8 @@ public class MessageParser extends AbstractParser implements Consumer<im.convers
message.getReactions(),
reactions.getReactions(),
isReceived,
- reactionFrom);
+ reactionFrom,
+ message.getRemoteMsgId());
message.setReactions(combinedReactions);
mXmppConnectionService.updateMessage(message, false);
}
@@ -5288,7 +5288,8 @@ public class XmppConnectionService extends Service {
false,
self.getFullJid(),
conversation.getAccount().getJid(),
- occupantId);
+ occupantId,
+ null);
} else {
if (message.isCarbon() || message.getStatus() == Message.STATUS_RECEIVED) {
reactToId = message.getRemoteMsgId();
@@ -5300,7 +5301,8 @@ public class XmppConnectionService extends Service {
message.getReactions(),
reactions,
false,
- conversation.getAccount().getJid());
+ conversation.getAccount().getJid(),
+ null);
}
if (Strings.isNullOrEmpty(reactToId)) {
return false;
@@ -32,15 +32,16 @@ public class BindingAdapters {
final Reaction.Aggregated reactions,
final Consumer<Collection<String>> onModifiedReactions,
final Consumer<EmojiSearch.CustomEmoji> onCustomReaction,
+ final Consumer<Reaction> onCustomReactionRemove,
final Runnable addReaction) {
- setReactions(chipGroup, conversation, reactions, true, onModifiedReactions, onCustomReaction, addReaction);
+ setReactions(chipGroup, conversation, reactions, true, onModifiedReactions, onCustomReaction, onCustomReactionRemove, addReaction);
}
public static void setReactionsOnSent(
final ChipGroup chipGroup,
final Reaction.Aggregated reactions,
final Consumer<Collection<String>> onModifiedReactions) {
- setReactions(chipGroup, null, reactions, false, onModifiedReactions, null, null);
+ setReactions(chipGroup, null, reactions, false, onModifiedReactions, null, null, null);
}
private static void setReactions(
@@ -50,6 +51,7 @@ public class BindingAdapters {
final boolean onReceived,
final Consumer<Collection<String>> onModifiedReactions,
final Consumer<EmojiSearch.CustomEmoji> onCustomReaction,
+ final Consumer<Reaction> onCustomReactionRemove,
final Runnable addReaction) {
final var context = chipGroup.getContext();
final var size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics());
@@ -71,9 +73,9 @@ public class BindingAdapters {
chip.setLayoutParams(layoutParams);
chip.setChipCornerRadius(corner);
emoji.setupChip(chip, count);
- final boolean oneOfOurs = aggregated.ourReactions.contains(emoji.toString());
+ final var oneOfOurs = reaction.getValue().stream().filter(r -> !r.received).findFirst();
// received = surface; sent = surface high matches bubbles
- if (oneOfOurs) {
+ if (oneOfOurs.isPresent()) {
chip.setChipBackgroundColor(
MaterialColors.getColorStateListOrNull(
context,
@@ -89,12 +91,16 @@ public class BindingAdapters {
chip.setTextStartPadding(0.0f);
chip.setOnClickListener(
v -> {
- if (oneOfOurs) {
- onModifiedReactions.accept(
+ if (oneOfOurs.isPresent()) {
+ if (emoji instanceof EmojiSearch.CustomEmoji) {
+ onCustomReactionRemove.accept(oneOfOurs.get());
+ } else {
+ onModifiedReactions.accept(
ImmutableSet.copyOf(
Collections2.filter(
aggregated.ourReactions,
r -> !r.equals(emoji.toString()))));
+ }
} else {
if (emoji instanceof EmojiSearch.CustomEmoji) {
onCustomReaction.accept((EmojiSearch.CustomEmoji) emoji);
@@ -1524,6 +1524,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
aggregatedReactions,
reactions -> sendReactions(message, reactions),
emoji -> sendCustomReaction(message, emoji),
+ reaction -> removeCustomReaction(conversation, reaction),
() -> addReaction(message));
} else if (type == SENT) {
final var aggregatedReactions = conversation instanceof Conversation ? ((Conversation) conversation).aggregatedReactionsFor(message, reactionThumbnailer) : message.getAggregatedReactions();
@@ -1533,6 +1534,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
aggregatedReactions,
reactions -> sendReactions(message, reactions),
emoji -> sendCustomReaction(message, emoji),
+ reaction -> removeCustomReaction(conversation, reaction),
() -> addReaction(message));
}
@@ -1615,6 +1617,26 @@ public class MessageAdapter extends ArrayAdapter<Message> {
new Thread(() -> activity.xmppConnectionService.sendMessage(message)).start();
}
+ private void removeCustomReaction(final Conversational conversation, final Reaction reaction) {
+ if (!(conversation instanceof Conversation)) {
+ Toast.makeText(activity, R.string.could_not_add_reaction, Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ final var message = new Message(conversation, " ", ((Conversation) conversation).getNextEncryption());
+ final var envelope = ((Conversation) conversation).findMessageWithUuidOrRemoteId(reaction.envelopeId);
+ if (envelope != null) {
+ ((Conversation) conversation).remove(envelope);
+ message.addPayload(envelope.getReply());
+ message.getOrMakeHtml();
+ message.putEdited(reaction.envelopeId, envelope.getServerMsgId());
+ } else {
+ message.putEdited(reaction.envelopeId, null);
+ }
+
+ new Thread(() -> activity.xmppConnectionService.sendMessage(message)).start();
+ }
+
private void addReaction(final Message message) {
activity.addReaction(message, reactions -> activity.xmppConnectionService.sendReactions(message,reactions));
}