add helper method to count reactions

This commit is contained in:
Daniel Gultsch 2023-02-12 17:25:26 +01:00
parent 7e2bff9d03
commit 2728a96ab9
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
7 changed files with 94 additions and 7 deletions

View file

@ -80,6 +80,48 @@ public class TransformationTest {
Assert.assertEquals(REMOTE, onlyReaction.reactionBy); Assert.assertEquals(REMOTE, onlyReaction.reactionBy);
} }
@Test
public void multipleReactions() {
final var group = Jid.ofEscaped("a@group.example.com");
final var message = new Message(Message.Type.GROUPCHAT);
message.addExtension(new Body("Please give me a thumbs up"));
message.setFrom(group.withResource("user-a"));
this.transformer.transform(
Transformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a"));
final var reactionA = new Message(Message.Type.GROUPCHAT);
reactionA.setFrom(group.withResource("user-b"));
reactionA.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b"));
final var reactionB = new Message(Message.Type.GROUPCHAT);
reactionB.setFrom(group.withResource("user-c"));
reactionB.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-c"));
final var reactionC = new Message(Message.Type.GROUPCHAT);
reactionC.setFrom(group.withResource("user-d"));
final var reactions = reactionC.addExtension(Reactions.to("stanza-a"));
reactions.addExtension(new Reaction("Y"));
reactions.addExtension(new Reaction("Z"));
this.transformer.transform(
Transformation.of(reactionC, Instant.now(), REMOTE, "stanza-d", "id-user-d"));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
final var dbMessage = Iterables.getOnlyElement(messages);
Assert.assertEquals(4, dbMessage.reactions.size());
final var aggregated = dbMessage.getAggregatedReactions();
final var mostFrequentReaction = Iterables.get(aggregated, 0);
Assert.assertEquals("Y", mostFrequentReaction.getKey());
Assert.assertEquals(3L, (long) mostFrequentReaction.getValue());
final var secondReaction = Iterables.get(aggregated, 1);
Assert.assertEquals("Z", secondReaction.getKey());
Assert.assertEquals(1L, (long) secondReaction.getValue());
}
@Test @Test
public void correctionBeforeOriginal() { public void correctionBeforeOriginal() {

View file

@ -1,6 +1,7 @@
package eu.siacs.conversations.xml; package eu.siacs.conversations.xml;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -159,18 +160,18 @@ public class Element {
return content; return content;
} }
public Element setAttribute(String name, String value) { public Element setAttribute(final String name, final String value) {
if (name != null && value != null) { Preconditions.checkArgument(name != null, "The attribute must have a name");
if (value == null) {
this.attributes.remove(name);
} else {
this.attributes.put(name, value); this.attributes.put(name, value);
} }
return this; return this;
} }
public Element setAttribute(String name, Jid value) { public Element setAttribute(final String name, final Jid value) {
if (name != null && value != null) { return this.setAttribute(name, value == null ? null : value.toEscapedString());
this.attributes.put(name, value.toEscapedString());
}
return this;
} }
public void removeAttribute(final String name) { public void removeAttribute(final String name) {

View file

@ -1,11 +1,17 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import androidx.room.Relation; import androidx.room.Relation;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.database.entity.MessageContentEntity; import im.conversations.android.database.entity.MessageContentEntity;
import im.conversations.android.database.entity.MessageReactionEntity; import im.conversations.android.database.entity.MessageReactionEntity;
import java.time.Instant; import java.time.Instant;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
public class MessageWithContentReactions { public class MessageWithContentReactions {
@ -34,4 +40,13 @@ public class MessageWithContentReactions {
parentColumn = "id", parentColumn = "id",
entityColumn = "messageEntityId") entityColumn = "messageEntityId")
public List<MessageReaction> reactions; public List<MessageReaction> reactions;
public Set<Map.Entry<String, Integer>> getAggregatedReactions() {
final Map<String, Integer> aggregatedReactions =
Maps.transformValues(
Multimaps.index(reactions, r -> r.reaction).asMap(), Collection::size);
return ImmutableSortedSet.copyOf(
(a, b) -> Integer.compare(b.getValue(), a.getValue()),
aggregatedReactions.entrySet());
}
} }

View file

@ -10,6 +10,11 @@ public class Body extends Extension {
super(Body.class); super(Body.class);
} }
public Body(final String content) {
this();
setContent(content);
}
public String getLang() { public String getLang() {
return this.getAttribute("xml:lang"); return this.getAttribute("xml:lang");
} }

View file

@ -9,4 +9,9 @@ public class Reaction extends Extension {
public Reaction() { public Reaction() {
super(Reaction.class); super(Reaction.class);
} }
public Reaction(final String reaction) {
this();
setContent(reaction);
}
} }

View file

@ -27,4 +27,10 @@ public class Reactions extends Extension {
public void setId(String id) { public void setId(String id) {
this.setAttribute("id", id); this.setAttribute("id", id);
} }
public static Reactions to(final String id) {
final var reactions = new Reactions();
reactions.setId(id);
return reactions;
}
} }

View file

@ -10,6 +10,11 @@ public class Message extends Stanza {
super(Message.class); super(Message.class);
} }
public Message(Type type) {
this();
this.setType(type);
}
public String getBody() { public String getBody() {
return this.findChildContent("body"); return this.findChildContent("body");
} }
@ -27,6 +32,14 @@ public class Message extends Stanza {
} }
} }
public void setType(final Type type) {
if (type == null || type == Type.NORMAL) {
this.removeAttribute("type");
} else {
this.setAttribute("type", type.toString().toLowerCase(Locale.ROOT));
}
}
public enum Type { public enum Type {
ERROR, ERROR,
NORMAL, NORMAL,