diff --git a/src/main/java/eu/siacs/conversations/entities/Reaction.java b/src/main/java/eu/siacs/conversations/entities/Reaction.java index 8df66035c65b7d641f757ba94dc7ab94ec0ef98e..ff9d5a1a88aaa40f349d668381bdb1575fa767b1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Reaction.java +++ b/src/main/java/eu/siacs/conversations/entities/Reaction.java @@ -209,13 +209,12 @@ public class Reaction { } public static Aggregated aggregated(final Collection reactions, Function thumbnailer) { - final Map aggregatedReactions = - Maps.transformValues( - Multimaps.index(reactions, r -> r.cid == null ? new EmojiSearch.Emoji(r.reaction, 0) : new EmojiSearch.CustomEmoji(r.reaction, r.cid.toString(), thumbnailer.apply(r).getThumbnail(r.cid), null)).asMap(), Collection::size); - final List> sortedList = + final Map> aggregatedReactions = + Multimaps.index(reactions, r -> r.cid == null ? new EmojiSearch.Emoji(r.reaction, 0) : new EmojiSearch.CustomEmoji(r.reaction, r.cid.toString(), thumbnailer.apply(r).getThumbnail(r.cid), null)).asMap(); + final List>> sortedList = Ordering.from( Comparator.comparingInt( - (Map.Entry o) -> o.getValue())) + (Map.Entry> o) -> o.getValue().size())) .reverse() .immutableSortedCopy(aggregatedReactions.entrySet()); return new Aggregated( @@ -228,11 +227,11 @@ public class Reaction { public static final class Aggregated { - public final List> reactions; + public final List>> reactions; public final Set ourReactions; private Aggregated( - final List> reactions, Set ourReactions) { + final List>> reactions, Set ourReactions) { this.reactions = reactions; this.ourReactions = ourReactions; } diff --git a/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java b/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java index 9ed6a8c5b05a0276adaa89f2a39716ded38546a1..c03c0efb295b86b94ce26e9ff12d171f0489cb7e 100644 --- a/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java +++ b/src/main/java/eu/siacs/conversations/ui/BindingAdapters.java @@ -9,37 +9,43 @@ import com.cheogram.android.EmojiSearch; import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; import com.google.android.material.color.MaterialColors; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableSet; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Reaction; +import eu.siacs.conversations.utils.UIHelper; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.stream.Collectors; public class BindingAdapters { public static void setReactionsOnReceived( final ChipGroup chipGroup, + final Conversation conversation, final Reaction.Aggregated reactions, final Consumer> onModifiedReactions, final Consumer onCustomReaction, final Runnable addReaction) { - setReactions(chipGroup, reactions, true, onModifiedReactions, onCustomReaction, addReaction); + setReactions(chipGroup, conversation, reactions, true, onModifiedReactions, onCustomReaction, addReaction); } public static void setReactionsOnSent( final ChipGroup chipGroup, final Reaction.Aggregated reactions, final Consumer> onModifiedReactions) { - setReactions(chipGroup, reactions, false, onModifiedReactions, null, null); + setReactions(chipGroup, null, reactions, false, onModifiedReactions, null, null); } private static void setReactions( final ChipGroup chipGroup, + final Conversation conversation, final Reaction.Aggregated aggregated, final boolean onReceived, final Consumer> onModifiedReactions, @@ -49,7 +55,7 @@ public class BindingAdapters { final var size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics()); final var corner = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics()); final var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, size); - final List> reactions = aggregated.reactions; + final List>> reactions = aggregated.reactions; if (reactions == null || reactions.isEmpty()) { chipGroup.setVisibility(View.GONE); } else { @@ -57,7 +63,7 @@ public class BindingAdapters { chipGroup.setVisibility(View.VISIBLE); for (final var reaction : reactions) { final var emoji = reaction.getKey(); - final var count = reaction.getValue(); + final var count = reaction.getValue().size(); final Chip chip = new Chip(chipGroup.getContext()); //chip.setEnsureMinTouchTargetSize(false); chip.setChipMinHeight(size-32.0f); @@ -101,6 +107,14 @@ public class BindingAdapters { } } }); + chip.setOnLongClickListener(v -> { + final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context); + builder.setTitle(emoji.toString()); + builder.setMessage(reaction.getValue().stream().map(r -> UIHelper.getDisplayName(conversation, r)).collect(Collectors.joining("\n"))); + builder.setPositiveButton(context.getResources().getString(R.string.ok), null); + builder.create().show(); + return true; + }); chipGroup.addView(chip); } if (addReaction != null) { 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 607f6149811dd1e2817558c7baf5f019aa9f9ef2..396e5cfe3035ded2e210ae7f3d5b1f60b167dad2 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1520,6 +1520,7 @@ public class MessageAdapter extends ArrayAdapter { final var aggregatedReactions = conversation instanceof Conversation ? ((Conversation) conversation).aggregatedReactionsFor(message, reactionThumbnailer) : message.getAggregatedReactions(); BindingAdapters.setReactionsOnReceived( viewHolder.reactions, + conversation instanceof Conversation ? (Conversation) conversation : null, aggregatedReactions, reactions -> sendReactions(message, reactions), emoji -> sendCustomReaction(message, emoji), @@ -1528,6 +1529,7 @@ public class MessageAdapter extends ArrayAdapter { final var aggregatedReactions = conversation instanceof Conversation ? ((Conversation) conversation).aggregatedReactionsFor(message, reactionThumbnailer) : message.getAggregatedReactions(); BindingAdapters.setReactionsOnReceived( viewHolder.reactions, + conversation instanceof Conversation ? (Conversation) conversation : null, aggregatedReactions, reactions -> sendReactions(message, reactions), emoji -> sendCustomReaction(message, emoji), diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 4f7640113037a97d557e5e0c3d825735b1f2de32..8c9afc22e86909807f7f5629e428dcf22e61d9d2 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -39,6 +39,7 @@ import eu.siacs.conversations.entities.Conversational; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presence; +import eu.siacs.conversations.entities.Reaction; import eu.siacs.conversations.entities.RtpSessionStatus; import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.services.XmppConnectionService; @@ -503,6 +504,22 @@ public class UIHelper { } } + public static String getDisplayName(final Conversational conversation, final Reaction reaction) { + if (conversation.getMode() == Conversation.MODE_MULTI) { + if (conversation instanceof Conversation) { + MucOptions.User user = ((Conversation) conversation).getMucOptions().findUserByFullJid(reaction.trueJid); + if (user == null) user = ((Conversation) conversation).getMucOptions().findUserByOccupantId(reaction.occupantId, reaction.from); + if (user != null) { + final String dname = getDisplayName(user); + if (dname != null) return dname; + } + } + return getDisplayedMucCounterpart(reaction.from); + } + + return conversation == null ? reaction.from.asBareJid().toString() : conversation.getAccount().getRoster().getContact(reaction.from).getDisplayName(); + } + public static String getMessageHint(final Context context,final Conversation conversation) { return switch (conversation.getNextEncryption()) { case Message.ENCRYPTION_NONE -> {