diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 0acca4600d7df8d3fd7cb5f8364dd9a024985b7c..524164bba0aa2d7949ed67dfecde830f824e2a61 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -5,6 +5,10 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.services.AvatarService; @@ -20,6 +24,7 @@ import eu.siacs.conversations.xmpp.pep.Avatar; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -331,12 +336,19 @@ public class MucOptions { return null; } + public User findUserByOccupantId(final String occupantId) { + synchronized (this.users) { + return Strings.isNullOrEmpty(occupantId) ? null : Iterables.find(this.users, u -> occupantId.equals(u.occupantId),null); + } + } + public User findOrCreateUserByRealJid(Jid jid, Jid fullJid) { - User user = findUserByRealJid(jid); - if (user == null) { - user = new User(this, fullJid); - user.setRealJid(jid); + final User existing = findUserByRealJid(jid); + if (existing != null) { + return existing; } + final var user = new User(this, fullJid); + user.setRealJid(jid); return user; } @@ -350,6 +362,31 @@ public class MucOptions { } } + private User findUser(final Reaction reaction) { + if (reaction.trueJid != null) { + return findOrCreateUserByRealJid(reaction.trueJid.asBareJid(), reaction.from); + } + final var existing = findUserByOccupantId(reaction.occupantId); + if (existing != null) { + return existing; + } else if (reaction.from != null) { + return new User(this,reaction.from); + } else { + return null; + } + } + + public List findUsers(final Collection reactions) { + final ImmutableList.Builder builder = new ImmutableList.Builder<>(); + for(final Reaction reaction : reactions) { + final var user = findUser(reaction); + if (user != null) { + builder.add(user); + } + } + return builder.build(); + } + public boolean isContactInRoom(Contact contact) { return contact != null && findUserByRealJid(contact.getJid().asBareJid()) != null; } diff --git a/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java b/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java index 6f6b4e8bebba341dbc61ca9c81ec7cb747167b95..e8d860daae4248090c753e70e4289019befe3d5f 100644 --- a/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java +++ b/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Consumer; +import java.util.function.Function; public class BindingAdapters { @@ -23,15 +24,18 @@ public class BindingAdapters { final ChipGroup chipGroup, final Reaction.Aggregated reactions, final Consumer> onModifiedReactions, + final Function onDetailsClicked, final Runnable addReaction) { - setReactions(chipGroup, reactions, true, onModifiedReactions, addReaction); + setReactions( + chipGroup, reactions, true, onModifiedReactions, onDetailsClicked, addReaction); } public static void setReactionsOnSent( final ChipGroup chipGroup, final Reaction.Aggregated reactions, - final Consumer> onModifiedReactions) { - setReactions(chipGroup, reactions, false, onModifiedReactions, null); + final Consumer> onModifiedReactions, + final Function onDetailsClicked) { + setReactions(chipGroup, reactions, false, onModifiedReactions, onDetailsClicked, null); } private static void setReactions( @@ -39,6 +43,7 @@ public class BindingAdapters { final Reaction.Aggregated aggregated, final boolean onReceived, final Consumer> onModifiedReactions, + final Function onDetailsClicked, final Runnable addReaction) { final var context = chipGroup.getContext(); final List> reactions = aggregated.reactions; @@ -89,6 +94,7 @@ public class BindingAdapters { .build()); } }); + chip.setOnLongClickListener(v -> onDetailsClicked.apply(emoji)); chipGroup.addView(chip); } if (onReceived) { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index caa0d3667bf930dcffda0ff3376db6b1efbb54b1..5ed24dfb12b6c7196a0c1f3366fdc01b0ac07767 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -45,8 +45,10 @@ import com.google.android.material.color.MaterialColors; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.common.base.Joiner; import com.google.common.base.Strings; +import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import eu.siacs.conversations.AppSettings; import eu.siacs.conversations.Config; @@ -1077,18 +1079,41 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.reactions, message.getAggregatedReactions(), reactions -> sendReactions(message, reactions), + emoji -> showDetailedReaction(message, emoji), () -> addReaction(message)); } else if (type == SENT) { BindingAdapters.setReactionsOnSent( viewHolder.reactions, message.getAggregatedReactions(), - reactions -> sendReactions(message, reactions)); + reactions -> sendReactions(message, reactions), + emoji -> showDetailedReaction(message, emoji)); } displayStatus(viewHolder, message, type, bubbleColor); return view; } + private boolean showDetailedReaction(final Message message, final String emoji) { + final var c = message.getConversation(); + if (c instanceof Conversation conversation && c.getMode() == Conversational.MODE_MULTI) { + final var reactions = + Collections2.filter(message.getReactions(), r -> r.reaction.equals(emoji)); + final var mucOptions = conversation.getMucOptions(); + final var users = mucOptions.findUsers(reactions); + if (users.isEmpty()) { + return true; + } + final MaterialAlertDialogBuilder dialogBuilder = + new MaterialAlertDialogBuilder(activity); + dialogBuilder.setTitle(emoji); + dialogBuilder.setMessage(UIHelper.concatNames(users)); + dialogBuilder.create().show(); + return true; + } else { + return false; + } + } + private void sendReactions(final Message message, final Collection reactions) { if (activity.xmppConnectionService.sendReactions(message, reactions)) { return;