diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/EmojiCount.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/EmojiCount.java index c5dcbc6396..88842356c6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/EmojiCount.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/EmojiCount.java @@ -3,16 +3,22 @@ package org.thoughtcrime.securesms.reactions; import androidx.annotation.NonNull; final class EmojiCount { - private final String emoji; - private final int count; + private final String baseEmoji; + private final String displayEmoji; + private final int count; - EmojiCount(@NonNull String emoji, int count) { - this.emoji = emoji; - this.count = count; + EmojiCount(@NonNull String baseEmoji, @NonNull String emoji, int count) { + this.baseEmoji = baseEmoji; + this.displayEmoji = emoji; + this.count = count; } - public @NonNull String getEmoji() { - return emoji; + public @NonNull String getBaseEmoji() { + return baseEmoji; + } + + public @NonNull String getDisplayEmoji() { + return displayEmoji; } public int getCount() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionEmojiCountAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionEmojiCountAdapter.java index 1f52392a9c..07b1be83bb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionEmojiCountAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionEmojiCountAdapter.java @@ -38,7 +38,7 @@ final class ReactionEmojiCountAdapter extends RecyclerView.Adapter { if (position != -1 && position != selectedPosition) { - onEmojiCountSelectedListener.onSelected(position == 0 ? null : emojiCountList.get(position - 1).getEmoji()); + onEmojiCountSelectedListener.onSelected(position == 0 ? null : emojiCountList.get(position - 1).getBaseEmoji()); int oldPosition = selectedPosition; selectedPosition = position; @@ -83,7 +83,7 @@ final class ReactionEmojiCountAdapter extends RecyclerView.Adapter reactions = new ArrayList<>(counters.values()); @@ -126,7 +128,7 @@ public class ReactionsConversationView extends LinearLayout { List shortened = new ArrayList<>(3); shortened.add(reactions.get(0)); shortened.add(reactions.get(1)); - shortened.add(Stream.of(reactions).skip(2).reduce(new Reaction(null, 0, 0, false), Reaction::merge)); + shortened.add(Stream.of(reactions).skip(2).reduce(new Reaction(null, null, 0, 0, false), Reaction::merge)); return shortened; } else { @@ -140,8 +142,8 @@ public class ReactionsConversationView extends LinearLayout { TextView countView = root.findViewById(R.id.reactions_pill_count); View spacer = root.findViewById(R.id.reactions_pill_spacer); - if (reaction.emoji != null) { - emojiView.setText(reaction.emoji); + if (reaction.displayEmoji != null) { + emojiView.setText(reaction.displayEmoji); if (reaction.count > 1) { countView.setText(String.valueOf(reaction.count)); @@ -166,19 +168,27 @@ public class ReactionsConversationView extends LinearLayout { } private static class Reaction implements Comparable { - private String emoji; + private String baseEmoji; + private String displayEmoji; private int count; private long lastSeen; private boolean userWasSender; - Reaction(@Nullable String emoji, int count, long lastSeen, boolean userWasSender) { - this.emoji = emoji; + Reaction(@Nullable String baseEmoji, @Nullable String displayEmoji, int count, long lastSeen, boolean userWasSender) { + this.baseEmoji = baseEmoji; + this.displayEmoji = displayEmoji; this.count = count; this.lastSeen = lastSeen; this.userWasSender = userWasSender; } - void update(long lastSeen, boolean userWasSender) { + void update(@NonNull String displayEmoji, long lastSeen, boolean userWasSender) { + if (!this.userWasSender) { + if (userWasSender || lastSeen > this.lastSeen) { + this.displayEmoji = displayEmoji; + } + } + this.count = this.count + 1; this.lastSeen = Math.max(this.lastSeen, lastSeen); this.userWasSender = this.userWasSender || userWasSender; diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsLoader.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsLoader.java index 148cbcc97c..4386732c01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsLoader.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsLoader.java @@ -6,18 +6,16 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.util.Pair; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Transformations; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import com.annimon.stream.Stream; +import org.thoughtcrime.securesms.components.emoji.EmojiUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.model.MessageRecord; -import org.thoughtcrime.securesms.database.model.ReactionRecord; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.AbstractCursorLoader; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; @@ -57,6 +55,7 @@ public class ReactionsLoader implements ReactionsViewModel.Repository, LoaderMan } else { internalLiveData.postValue(Stream.of(record.getReactions()) .map(reactionRecord -> new Reaction(Recipient.resolved(reactionRecord.getAuthor()), + EmojiUtil.getCanonicalRepresentation(reactionRecord.getEmoji()), reactionRecord.getEmoji(), reactionRecord.getDateReceived())) .toList()); @@ -106,21 +105,27 @@ public class ReactionsLoader implements ReactionsViewModel.Repository, LoaderMan static class Reaction { private final Recipient sender; - private final String emoji; + private final String baseEmoji; + private final String displayEmoji; private final long timestamp; - private Reaction(@NonNull Recipient sender, @NonNull String emoji, long timestamp) { - this.sender = sender; - this.emoji = emoji; - this.timestamp = timestamp; + private Reaction(@NonNull Recipient sender, @NonNull String baseEmoji, @NonNull String displayEmoji, long timestamp) { + this.sender = sender; + this.baseEmoji = baseEmoji; + this.displayEmoji = displayEmoji; + this.timestamp = timestamp; } public @NonNull Recipient getSender() { return sender; } - public @NonNull String getEmoji() { - return emoji; + public @NonNull String getBaseEmoji() { + return baseEmoji; + } + + public @NonNull String getDisplayEmoji() { + return displayEmoji; } public long getTimestamp() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsViewModel.java index 13cc681e53..9fcb1d7f93 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsViewModel.java @@ -27,16 +27,16 @@ public class ReactionsViewModel extends ViewModel { return Transformations.switchMap(filterEmoji, emoji -> Transformations.map(repository.getReactions(), reactions -> Stream.of(reactions) - .filter(reaction -> emoji == null || reaction.getEmoji().equals(emoji)) + .filter(reaction -> emoji == null || reaction.getBaseEmoji().equals(emoji)) .toList())); } public @NonNull LiveData> getEmojiCounts() { return Transformations.map(repository.getReactions(), reactionList -> Stream.of(reactionList) - .groupBy(Reaction::getEmoji) + .groupBy(Reaction::getBaseEmoji) .sorted(this::compareReactions) - .map(entry -> new EmojiCount(entry.getKey(), entry.getValue().size())) + .map(entry -> new EmojiCount(entry.getKey(), getCountDisplayEmoji(entry.getValue()), entry.getValue().size())) .toList()); } @@ -61,6 +61,16 @@ public class ReactionsViewModel extends ViewModel { .orElse(-1L); } + private @NonNull String getCountDisplayEmoji(@NonNull List reactions) { + for (Reaction reaction : reactions) { + if (reaction.getSender().isLocalNumber()) { + return reaction.getDisplayEmoji(); + } + } + + return reactions.get(reactions.size() - 1).getDisplayEmoji(); + } + interface Repository { LiveData> getReactions(); }