From 73160d4d26d44d0fbc367119dd2a277a59832bb6 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 31 Jan 2020 15:10:59 -0500 Subject: [PATCH] Update reactions UI. --- .../conversation/ConversationItem.java | 28 ++- .../ConversationItemReactionBubbles.java | 177 ---------------- .../ConversationSwipeAnimationHelper.java | 2 +- .../database/model/ReactionRecord.java | 18 ++ .../megaphone/MegaphoneRepository.java | 3 +- .../reactions/ReactionsConversationView.java | 198 ++++++++++++++++++ .../thoughtcrime/securesms/util/ViewUtil.java | 10 + ....xml => reaction_pill_background_dark.xml} | 10 +- ...xml => reaction_pill_background_light.xml} | 10 +- ...reaction_pill_background_selected_dark.xml | 6 + ...action_pill_background_selected_light.xml} | 10 +- .../reactions_send_background_dark.xml | 8 - .../res/layout/conversation_item_received.xml | 40 +--- .../res/layout/conversation_item_sent.xml | 36 +--- app/src/main/res/layout/reactions_pill.xml | 35 ++++ app/src/main/res/values/attrs.xml | 9 +- app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/themes.xml | 13 +- 18 files changed, 339 insertions(+), 277 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemReactionBubbles.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsConversationView.java rename app/src/main/res/drawable/{reactions_recv_background_dark.xml => reaction_pill_background_dark.xml} (55%) rename app/src/main/res/drawable/{reactions_recv_background_light.xml => reaction_pill_background_light.xml} (56%) create mode 100644 app/src/main/res/drawable/reaction_pill_background_selected_dark.xml rename app/src/main/res/drawable/{reactions_send_background_light.xml => reaction_pill_background_selected_light.xml} (56%) delete mode 100644 app/src/main/res/drawable/reactions_send_background_dark.xml create mode 100644 app/src/main/res/layout/reactions_pill.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java index d9aff3e6ad..b14f94f86c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -42,6 +42,7 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -97,6 +98,7 @@ import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideClickListener; import org.thoughtcrime.securesms.mms.SlidesClickedListener; import org.thoughtcrime.securesms.mms.TextSlide; +import org.thoughtcrime.securesms.reactions.ReactionsConversationView; import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientForeverObserver; @@ -158,7 +160,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati private AvatarImageView contactPhoto; private AlertView alertView; private ViewGroup container; - protected ViewGroup reactionsContainer; + protected ReactionsConversationView reactionsView; private @NonNull Set batchSelected = new HashSet<>(); private @NonNull Outliner outliner = new Outliner(); @@ -171,7 +173,6 @@ public class ConversationItem extends LinearLayout implements BindableConversati private Stub stickerStub; private Stub revealableStub; private @Nullable EventListener eventListener; - private ConversationItemReactionBubbles conversationItemReactionBubbles; private int defaultBubbleColor; private int measureCalls; @@ -226,9 +227,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati this.quoteView = findViewById(R.id.quote_view); this.container = findViewById(R.id.container); this.reply = findViewById(R.id.reply_icon); - this.reactionsContainer = findViewById(R.id.reactions_bubbles_container); - - this.conversationItemReactionBubbles = new ConversationItemReactionBubbles(this.reactionsContainer); + this.reactionsView = findViewById(R.id.reactions_view); setOnClickListener(new ClickListener(null)); @@ -906,8 +905,23 @@ public class ConversationItem extends LinearLayout implements BindableConversati } private void setReactions(@NonNull MessageRecord current) { - conversationItemReactionBubbles.setReactions(current.getReactions()); - reactionsContainer.setOnClickListener(v -> { + if (current.getReactions().isEmpty()) { + reactionsView.clear(); + return; + } + + bodyBubble.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + setReactionsWithWidth(current); + bodyBubble.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + }); + } + + private void setReactionsWithWidth(@NonNull MessageRecord current) { + reactionsView.setReactions(current.getReactions(), bodyBubble.getWidth()); + reactionsView.setOnClickListener(v -> { if (eventListener == null) return; eventListener.onReactionClicked(current.getId(), current.isMms()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemReactionBubbles.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemReactionBubbles.java deleted file mode 100644 index 7f6d002b5b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemReactionBubbles.java +++ /dev/null @@ -1,177 +0,0 @@ -package org.thoughtcrime.securesms.conversation; - -import android.graphics.drawable.Drawable; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.util.Pair; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.components.emoji.EmojiImageView; -import org.thoughtcrime.securesms.database.model.ReactionRecord; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.util.ThemeUtil; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -final class ConversationItemReactionBubbles { - - private final ViewGroup reactionsContainer; - private final EmojiImageView primaryEmojiReaction; - private final EmojiImageView secondaryEmojiReaction; - - ConversationItemReactionBubbles(@NonNull ViewGroup reactionsContainer) { - this.reactionsContainer = reactionsContainer; - this.primaryEmojiReaction = reactionsContainer.findViewById(R.id.reactions_bubbles_primary); - this.secondaryEmojiReaction = reactionsContainer.findViewById(R.id.reactions_bubbles_secondary); - } - - void setReactions(@NonNull List reactions) { - if (reactions.size() == 0) { - hideAllReactions(); - return; - } - - final Collection reactionInfos = getReactionInfos(reactions); - - if (reactionInfos.size() == 1) { - displaySingleReaction(reactionInfos.iterator().next()); - } else { - displayMultipleReactions(reactionInfos); - } - } - - private static @NonNull Collection getReactionInfos(@NonNull List reactions) { - final Map counters = new HashMap<>(); - - for (ReactionRecord reaction : reactions) { - - ReactionInfo info = counters.get(reaction.getEmoji()); - if (info == null) { - info = new ReactionInfo(reaction.getEmoji(), - 1, - reaction.getDateReceived(), - Recipient.self().getId().equals(reaction.getAuthor())); - } else { - info = new ReactionInfo(reaction.getEmoji(), - info.count + 1, - Math.max(info.lastSeen, reaction.getDateReceived()), - info.userWasSender || Recipient.self().getId().equals(reaction.getAuthor())); - } - - counters.put(reaction.getEmoji(), info); - } - - return counters.values(); - } - - private void hideAllReactions() { - reactionsContainer.setVisibility(View.GONE); - } - - private void displaySingleReaction(@NonNull ReactionInfo reactionInfo) { - reactionsContainer.setVisibility(View.VISIBLE); - primaryEmojiReaction.setVisibility(View.VISIBLE); - secondaryEmojiReaction.setVisibility(View.GONE); - - primaryEmojiReaction.setImageEmoji(reactionInfo.emoji); - primaryEmojiReaction.setBackground(getBackgroundDrawableForReactionBubble(reactionInfo)); - } - - private void displayMultipleReactions(@NonNull Collection reactionInfos) { - reactionsContainer.setVisibility(View.VISIBLE); - primaryEmojiReaction.setVisibility(View.VISIBLE); - secondaryEmojiReaction.setVisibility(View.VISIBLE); - - Pair primaryAndSecondaryReactions = getPrimaryAndSecondaryReactions(reactionInfos); - primaryEmojiReaction.setImageEmoji(primaryAndSecondaryReactions.first.emoji); - primaryEmojiReaction.setBackground(getBackgroundDrawableForReactionBubble(primaryAndSecondaryReactions.first)); - secondaryEmojiReaction.setImageEmoji(primaryAndSecondaryReactions.second.emoji); - secondaryEmojiReaction.setBackground(getBackgroundDrawableForReactionBubble(primaryAndSecondaryReactions.second)); - } - - private Drawable getBackgroundDrawableForReactionBubble(@NonNull ReactionInfo reactionInfo) { - return ThemeUtil.getThemedDrawable(reactionsContainer.getContext(), - reactionInfo.userWasSender ? R.attr.reactions_sent_background : R.attr.reactions_recv_background); - } - - private Pair getPrimaryAndSecondaryReactions(@NonNull Collection reactionInfos) { - ReactionInfo mostPopular = null; - ReactionInfo latestReaction = null; - ReactionInfo secondLatestReaction = null; - ReactionInfo ourReaction = null; - - for (ReactionInfo current : reactionInfos) { - if (current.userWasSender) { - ourReaction = current; - } - - if (mostPopular == null) { - mostPopular = current; - } else if (mostPopular.count < current.count) { - mostPopular = current; - } - - if (latestReaction == null) { - latestReaction = current; - } else if (latestReaction.lastSeen < current.lastSeen) { - - if (current.count == mostPopular.count) { - mostPopular = current; - } - - secondLatestReaction = latestReaction; - latestReaction = current; - } else if (secondLatestReaction == null) { - secondLatestReaction = current; - } - } - - if (mostPopular == null) { - throw new AssertionError("getPrimaryAndSecondaryReactions was called with an empty list."); - } - - if (ourReaction != null && !mostPopular.equals(ourReaction)) { - return Pair.create(mostPopular, ourReaction); - } else { - return Pair.create(mostPopular, mostPopular.equals(latestReaction) ? secondLatestReaction : latestReaction); - } - } - - private static class ReactionInfo { - private final String emoji; - private final int count; - private final long lastSeen; - private final boolean userWasSender; - - private ReactionInfo(@NonNull String emoji, int count, long lastSeen, boolean userWasSender) { - this.emoji = emoji; - this.count = count; - this.lastSeen = lastSeen; - this.userWasSender = userWasSender; - } - - @Override - public int hashCode() { - return Objects.hash(emoji, count, lastSeen, userWasSender); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof ReactionInfo)) return false; - - ReactionInfo other = (ReactionInfo) obj; - - return other.emoji.equals(emoji) && - other.count == count && - other.lastSeen == lastSeen && - other.userWasSender == userWasSender; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSwipeAnimationHelper.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSwipeAnimationHelper.java index 1ae897475b..dac6af5e86 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSwipeAnimationHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSwipeAnimationHelper.java @@ -33,7 +33,7 @@ final class ConversationSwipeAnimationHelper { float progress = dx / TRIGGER_DX; updateBodyBubbleTransition(conversationItem.bodyBubble, dx, sign); - updateReactionsTransition(conversationItem.reactionsContainer, dx, sign); + updateReactionsTransition(conversationItem.reactionsView, dx, sign); updateReplyIconTransition(conversationItem.reply, dx, progress, sign); updateContactPhotoHolderTransition(conversationItem.contactPhotoHolder, progress, sign); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.java index c597190c17..f333362a42 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.java @@ -4,6 +4,8 @@ import androidx.annotation.NonNull; import org.thoughtcrime.securesms.recipients.RecipientId; +import java.util.Objects; + public class ReactionRecord { private final String emoji; private final RecipientId author; @@ -36,4 +38,20 @@ public class ReactionRecord { public long getDateReceived() { return dateReceived; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReactionRecord that = (ReactionRecord) o; + return dateSent == that.dateSent && + dateReceived == that.dateReceived && + Objects.equals(emoji, that.emoji) && + Objects.equals(author, that.author); + } + + @Override + public int hashCode() { + return Objects.hash(emoji, author, dateSent, dateReceived); + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneRepository.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneRepository.java index c10b806901..436e5b4a68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneRepository.java @@ -49,7 +49,8 @@ public class MegaphoneRepository { @MainThread public void onFirstEverAppLaunch() { executor.execute(() -> { - // Future megaphones we don't want to show to new users should get marked as finished here. + database.markFinished(Event.REACTIONS); + resetDatabaseCache(); }); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsConversationView.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsConversationView.java new file mode 100644 index 0000000000..c341ecb2fd --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsConversationView.java @@ -0,0 +1,198 @@ +package org.thoughtcrime.securesms.reactions; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.annimon.stream.Stream; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.database.model.ReactionRecord; +import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.util.ThemeUtil; +import org.thoughtcrime.securesms.util.ViewUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ReactionsConversationView extends LinearLayout { + + private static final int OUTER_MARGIN = ViewUtil.dpToPx(6); + + private boolean outgoing; + private List records; + + public ReactionsConversationView(Context context) { + super(context); + init(null); + } + + public ReactionsConversationView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(attrs); + } + + private void init(@Nullable AttributeSet attrs) { + records = new ArrayList<>(); + + if (attrs != null) { + TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.ReactionsConversationView, 0, 0); + outgoing = typedArray.getBoolean(R.styleable.ReactionsConversationView_rcv_outgoing, false); + } + } + + public void clear() { + removeAllViews(); + } + + public void setReactions(@NonNull List records, int bubbleWidth) { + if (records.equals(this.records)) { + return; + } + + this.records.clear(); + this.records.addAll(records); + + List reactions = buildSortedReactionsList(records); + + removeAllViews(); + + for (Reaction reaction : reactions) { + addView(buildPill(getContext(), this, reaction)); + } + + measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + + int railWidth = getMeasuredWidth(); + + if (railWidth < (bubbleWidth - OUTER_MARGIN)) { + int margin = (bubbleWidth - railWidth - OUTER_MARGIN); + + if (outgoing) { + ViewUtil.setRightMargin(this, margin); + } else { + ViewUtil.setLeftMargin(this, margin); + } + } else { + if (outgoing) { + ViewUtil.setRightMargin(this, OUTER_MARGIN); + } else { + ViewUtil.setLeftMargin(this, OUTER_MARGIN); + } + } + } + + private static @NonNull List buildSortedReactionsList(@NonNull List records) { + Map counters = new LinkedHashMap<>(); + RecipientId selfId = Recipient.self().getId(); + + for (ReactionRecord record : records) { + Reaction info = counters.get(record.getEmoji()); + + if (info == null) { + info = new Reaction(record.getEmoji(), 1, record.getDateReceived(), selfId.equals(record.getAuthor())); + } else { + info.update(record.getDateReceived(), selfId.equals(record.getAuthor())); + } + + counters.put(record.getEmoji(), info); + } + + List reactions = new ArrayList<>(counters.values()); + + Collections.sort(reactions, Collections.reverseOrder()); + + if (reactions.size() > 3) { + 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)); + + return shortened; + } else { + return reactions; + } + } + + private static View buildPill(@NonNull Context context, @NonNull ViewGroup parent, @NonNull Reaction reaction) { + View root = LayoutInflater.from(context).inflate(R.layout.reactions_pill, parent, false); + TextView emojiView = root.findViewById(R.id.reactions_pill_emoji); + 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.count > 1) { + countView.setText(String.valueOf(reaction.count)); + } else { + countView.setVisibility(GONE); + spacer.setVisibility(GONE); + } + } else { + emojiView.setVisibility(GONE); + spacer.setVisibility(GONE); + countView.setText(context.getString(R.string.ReactionsConversationView_plus, reaction.count)); + } + + if (reaction.userWasSender) { + root.setBackground(ThemeUtil.getThemedDrawable(context, R.attr.reactions_pill_selected_background)); + countView.setTextColor(ThemeUtil.getThemedColor(context, R.attr.reactions_pill_selected_text_color)); + } else { + root.setBackground(ThemeUtil.getThemedDrawable(context, R.attr.reactions_pill_background)); + } + + return root; + } + + private static class Reaction implements Comparable { + private String emoji; + private int count; + private long lastSeen; + private boolean userWasSender; + + Reaction(@Nullable String emoji, int count, long lastSeen, boolean userWasSender) { + this.emoji = emoji; + this.count = count; + this.lastSeen = lastSeen; + this.userWasSender = userWasSender; + } + + void update(long lastSeen, boolean userWasSender) { + this.count = this.count + 1; + this.lastSeen = Math.max(this.lastSeen, lastSeen); + this.userWasSender = this.userWasSender || userWasSender; + } + + @NonNull Reaction merge(@NonNull Reaction other) { + this.count = this.count + other.count; + this.lastSeen = Math.max(this.lastSeen, other.lastSeen); + this.userWasSender = this.userWasSender || other.userWasSender; + return this; + } + + @Override + public int compareTo(Reaction rhs) { + Reaction lhs = this; + + if (lhs.count != rhs.count) { + return Integer.compare(lhs.count, rhs.count); + } + + return Long.compare(lhs.lastSeen, rhs.lastSeen); + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java index dbebbf022c..ba99406018 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java @@ -233,6 +233,16 @@ public class ViewUtil { view.requestLayout(); } + public static void setRightMargin(@NonNull View view, int margin) { + if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) { + ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin; + } else { + ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin; + } + view.forceLayout(); + view.requestLayout(); + } + public static void setTopMargin(@NonNull View view, int margin) { ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = margin; view.requestLayout(); diff --git a/app/src/main/res/drawable/reactions_recv_background_dark.xml b/app/src/main/res/drawable/reaction_pill_background_dark.xml similarity index 55% rename from app/src/main/res/drawable/reactions_recv_background_dark.xml rename to app/src/main/res/drawable/reaction_pill_background_dark.xml index 2b6aa5b590..210e3c9fcd 100644 --- a/app/src/main/res/drawable/reactions_recv_background_dark.xml +++ b/app/src/main/res/drawable/reaction_pill_background_dark.xml @@ -1,8 +1,6 @@ - + + - - \ No newline at end of file + + diff --git a/app/src/main/res/drawable/reactions_recv_background_light.xml b/app/src/main/res/drawable/reaction_pill_background_light.xml similarity index 56% rename from app/src/main/res/drawable/reactions_recv_background_light.xml rename to app/src/main/res/drawable/reaction_pill_background_light.xml index bdab4b535c..3ff042175a 100644 --- a/app/src/main/res/drawable/reactions_recv_background_light.xml +++ b/app/src/main/res/drawable/reaction_pill_background_light.xml @@ -1,8 +1,6 @@ - + + - - \ No newline at end of file + + diff --git a/app/src/main/res/drawable/reaction_pill_background_selected_dark.xml b/app/src/main/res/drawable/reaction_pill_background_selected_dark.xml new file mode 100644 index 0000000000..534d363c44 --- /dev/null +++ b/app/src/main/res/drawable/reaction_pill_background_selected_dark.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/reactions_send_background_light.xml b/app/src/main/res/drawable/reaction_pill_background_selected_light.xml similarity index 56% rename from app/src/main/res/drawable/reactions_send_background_light.xml rename to app/src/main/res/drawable/reaction_pill_background_selected_light.xml index 8a6891ecb0..a76054a82e 100644 --- a/app/src/main/res/drawable/reactions_send_background_light.xml +++ b/app/src/main/res/drawable/reaction_pill_background_selected_light.xml @@ -1,8 +1,6 @@ - + + - - \ No newline at end of file + + diff --git a/app/src/main/res/drawable/reactions_send_background_dark.xml b/app/src/main/res/drawable/reactions_send_background_dark.xml deleted file mode 100644 index fac02c4dca..0000000000 --- a/app/src/main/res/drawable/reactions_send_background_dark.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_item_received.xml b/app/src/main/res/layout/conversation_item_received.xml index 15565e90aa..46fe18a0e5 100644 --- a/app/src/main/res/layout/conversation_item_received.xml +++ b/app/src/main/res/layout/conversation_item_received.xml @@ -200,7 +200,7 @@ android:layout_marginStart="@dimen/message_bubble_horizontal_padding" android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" android:layout_marginBottom="@dimen/message_bubble_bottom_padding" - android:gravity="end" + android:gravity="start" android:clipChildren="false" android:clipToPadding="false" android:alpha="0.7" @@ -214,7 +214,7 @@ android:layout_marginTop="6dp" android:layout_marginStart="@dimen/message_bubble_horizontal_padding" android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" - android:gravity="end" + android:gravity="start" android:clipChildren="false" android:clipToPadding="false" android:visibility="gone" @@ -231,35 +231,15 @@ android:orientation="vertical" android:gravity="center_vertical"/> - - - - - - - + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="-8dp" + android:layout_below="@id/body_bubble" + android:layout_alignStart="@id/body_bubble" + app:rcv_outgoing="false"/> diff --git a/app/src/main/res/layout/conversation_item_sent.xml b/app/src/main/res/layout/conversation_item_sent.xml index 154d49b073..3ddfd3af12 100644 --- a/app/src/main/res/layout/conversation_item_sent.xml +++ b/app/src/main/res/layout/conversation_item_sent.xml @@ -188,35 +188,15 @@ android:orientation="vertical" android:paddingBottom="4dp" /> - - - - - - - + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="-8dp" + android:layout_below="@id/body_bubble" + android:layout_alignEnd="@id/body_bubble" + app:rcv_outgoing="true"/> diff --git a/app/src/main/res/layout/reactions_pill.xml b/app/src/main/res/layout/reactions_pill.xml new file mode 100644 index 0000000000..ecc1417647 --- /dev/null +++ b/app/src/main/res/layout/reactions_pill.xml @@ -0,0 +1,35 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 374bfa0c9e..e06e75f949 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -97,11 +97,13 @@ - - + + + + @@ -447,4 +449,7 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4e4ae7637..612359a8bc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -666,6 +666,9 @@ Later Whoops, the Play Store app does not appear to be installed on your device. + + +%1$d + Block this contact? You will no longer receive messages and calls from this contact. diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index fc76fec442..6a84dd0f36 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -270,11 +270,13 @@ @drawable/ic_emoji_emoticon_light_20 @drawable/emoji_variation_selector_background_light - @drawable/reactions_recv_background_light - @drawable/reactions_send_background_light @drawable/reactions_old_background_dark @drawable/conversation_reaction_overlay_background_dark @drawable/reactions_bottom_sheet_dialog_fragment_emoji_item_selected_light + @drawable/reaction_pill_background_light + @drawable/reaction_pill_background_selected_light + @color/core_grey_60 + @color/core_grey_75 @color/core_grey_05 @color/core_grey_90 @@ -536,12 +538,13 @@ @color/transparent_white_90 @color/transparent_white_80 - @drawable/reactions_recv_background_dark - @drawable/reactions_send_background_dark @drawable/reactions_old_background_dark @drawable/conversation_reaction_overlay_background_dark @drawable/reactions_bottom_sheet_dialog_fragment_emoji_item_selected_dark - + @drawable/reaction_pill_background_dark + @drawable/reaction_pill_background_selected_dark + @color/core_grey_35 + @color/core_grey_15 @color/core_grey_85 @color/core_grey_65