mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-27 20:24:32 +01:00
Implement ability to react with any emoji behind a flag.
This commit is contained in:
@@ -197,6 +197,7 @@ import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
|
||||
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientExporter;
|
||||
@@ -269,7 +270,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
ComposeText.CursorPositionChangedListener,
|
||||
ConversationSearchBottomBar.EventListener,
|
||||
StickerKeyboardProvider.StickerEventListener,
|
||||
AttachmentKeyboard.Callback
|
||||
AttachmentKeyboard.Callback,
|
||||
ConversationReactionOverlay.OnReactionSelectedListener,
|
||||
ReactWithAnyEmojiBottomSheetDialogFragment.Callback
|
||||
{
|
||||
|
||||
private static final int SHORTCUT_ICON_SIZE = Build.VERSION.SDK_INT >= 26 ? ViewUtil.dpToPx(72) : ViewUtil.dpToPx(48 + 16 * 2);
|
||||
@@ -1714,7 +1717,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
inlineAttachmentButton.setOnClickListener(v -> handleAddAttachment());
|
||||
|
||||
reactionOverlay.setOnReactionSelectedListener(this::onReactionSelected);
|
||||
reactionOverlay.setOnReactionSelectedListener(this);
|
||||
}
|
||||
|
||||
protected void initializeActionBar() {
|
||||
@@ -1831,10 +1834,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
.show(TooltipPopup.POSITION_ABOVE);
|
||||
}
|
||||
|
||||
|
||||
private void onReactionSelected(MessageRecord messageRecord, String emoji) {
|
||||
@Override
|
||||
public void onReactionSelected(MessageRecord messageRecord, String emoji) {
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
reactionOverlay.hide();
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
ReactionRecord oldRecord = Stream.of(messageRecord.getReactions())
|
||||
.filter(record -> record.getAuthor().equals(Recipient.self().getId()))
|
||||
@@ -1849,6 +1854,35 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomReactionSelected(@NonNull MessageRecord messageRecord, boolean hasAddedCustomEmoji) {
|
||||
ReactionRecord oldRecord = Stream.of(messageRecord.getReactions())
|
||||
.filter(record -> record.getAuthor().equals(Recipient.self().getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (oldRecord != null && hasAddedCustomEmoji) {
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
reactionOverlay.hide();
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> MessageSender.sendReactionRemoval(context,
|
||||
messageRecord.getId(),
|
||||
messageRecord.isMms(),
|
||||
oldRecord));
|
||||
} else {
|
||||
reactionOverlay.hideAllButMask();
|
||||
|
||||
ReactWithAnyEmojiBottomSheetDialogFragment.createForMessageRecord(messageRecord)
|
||||
.show(getSupportFragmentManager(), "BOTTOM");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReactWithAnyEmojiDialogDismissed() {
|
||||
reactionOverlay.hideMask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSearchMoveUpPressed() {
|
||||
searchViewModel.onMoveUp();
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.widget.RelativeLayout;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.ConstraintSet;
|
||||
@@ -30,14 +31,17 @@ import com.annimon.stream.Stream;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.MaskView;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
||||
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.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
@@ -60,12 +64,13 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
private boolean downIsOurs;
|
||||
private boolean isToolbarTouch;
|
||||
private int selected = -1;
|
||||
private int customEmojiIndex;
|
||||
private int originalStatusBarColor;
|
||||
|
||||
private View backgroundView;
|
||||
private ConstraintLayout foregroundView;
|
||||
private View selectedView;
|
||||
private View[] emojiViews;
|
||||
private EmojiImageView[] emojiViews;
|
||||
private MaskView maskView;
|
||||
private Toolbar toolbar;
|
||||
|
||||
@@ -85,8 +90,10 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
private Toolbar.OnMenuItemClickListener onToolbarItemClickedListener;
|
||||
private OnHideListener onHideListener;
|
||||
|
||||
private AnimatorSet revealAnimatorSet = new AnimatorSet();
|
||||
private AnimatorSet hideAnimatorSet = new AnimatorSet();
|
||||
private AnimatorSet revealAnimatorSet = new AnimatorSet();
|
||||
private AnimatorSet hideAnimatorSet = new AnimatorSet();
|
||||
private AnimatorSet hideAllButMaskAnimatorSet = new AnimatorSet();
|
||||
private AnimatorSet hideMaskAnimatorSet = new AnimatorSet();
|
||||
|
||||
public ConversationReactionOverlay(@NonNull Context context) {
|
||||
super(context);
|
||||
@@ -111,7 +118,10 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
|
||||
emojiViews = Stream.of(ReactionEmoji.values())
|
||||
.map(e -> findViewById(e.viewId))
|
||||
.toArray(View[]::new);
|
||||
.toArray(EmojiImageView[]::new);
|
||||
|
||||
customEmojiIndex = FeatureFlags.reactWithAnyEmoji() ? ReactionEmoji.values().length - 1
|
||||
: ReactionEmoji.values().length;
|
||||
|
||||
distanceFromTouchDownPointToTopOfScrubberDeadZone = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_scrub_deadzone_distance_from_touch_top);
|
||||
distanceFromTouchDownPointToBottomOfScrubberDeadZone = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_scrub_deadzone_distance_from_touch_bottom);
|
||||
@@ -144,7 +154,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
selected = -1;
|
||||
|
||||
setupToolbarMenuItems();
|
||||
setupSelectedEmojiBackground();
|
||||
setupSelectedEmoji();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
View statusBarBackground = activity.findViewById(android.R.id.statusBarBackground);
|
||||
@@ -188,6 +198,22 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
|
||||
public void hide() {
|
||||
maskView.setTarget(null);
|
||||
hideInternal(hideAnimatorSet, onHideListener);
|
||||
}
|
||||
|
||||
public void hideAllButMask() {
|
||||
hideInternal(hideAllButMaskAnimatorSet, null);
|
||||
}
|
||||
|
||||
public void hideMask() {
|
||||
hideMaskAnimatorSet.start();
|
||||
|
||||
if (onHideListener != null) {
|
||||
onHideListener.onHide();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideInternal(@NonNull AnimatorSet hideAnimatorSet, @Nullable OnHideListener onHideListener) {
|
||||
overlayState = OverlayState.HIDDEN;
|
||||
|
||||
revealAnimatorSet.end();
|
||||
@@ -316,20 +342,30 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSelectedEmojiBackground() {
|
||||
private void setupSelectedEmoji() {
|
||||
final String oldEmoji = getOldEmoji(messageRecord);
|
||||
|
||||
if (oldEmoji == null) {
|
||||
selectedView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
boolean foundSelected = false;
|
||||
|
||||
for (int i = 0; i < emojiViews.length; i++) {
|
||||
final View view = emojiViews[i];
|
||||
final EmojiImageView view = emojiViews[i];
|
||||
|
||||
view.setScaleX(1.0f);
|
||||
view.setScaleY(1.0f);
|
||||
view.setTranslationY(0);
|
||||
|
||||
if (ReactionEmoji.values()[i].emoji.equals(oldEmoji)) {
|
||||
boolean isAtCustomIndex = i == customEmojiIndex;
|
||||
boolean isNotAtCustomIndexAndOldEmojiMatches = !isAtCustomIndex && ReactionEmoji.values()[i].emoji.equals(oldEmoji);
|
||||
boolean isAtCustomIndexAndOldEmojiExists = isAtCustomIndex && oldEmoji != null;
|
||||
|
||||
if (!foundSelected &&
|
||||
(isNotAtCustomIndexAndOldEmojiMatches || isAtCustomIndexAndOldEmojiExists))
|
||||
{
|
||||
foundSelected = true;
|
||||
selectedView.setVisibility(View.VISIBLE);
|
||||
|
||||
ConstraintSet constraintSet = new ConstraintSet();
|
||||
@@ -339,6 +375,18 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
constraintSet.connect(selectedView.getId(), ConstraintSet.LEFT, view.getId(), ConstraintSet.LEFT);
|
||||
constraintSet.connect(selectedView.getId(), ConstraintSet.RIGHT, view.getId(), ConstraintSet.RIGHT);
|
||||
constraintSet.applyTo(foregroundView);
|
||||
|
||||
if (isAtCustomIndex) {
|
||||
view.setImageEmoji(oldEmoji);
|
||||
view.setTag(oldEmoji);
|
||||
} else {
|
||||
view.setImageEmoji(ReactionEmoji.values()[i].emoji);
|
||||
}
|
||||
} else if (isAtCustomIndex) {
|
||||
view.setImageDrawable(AppCompatResources.getDrawable(getContext(), R.drawable.ic_any_emoji_32));
|
||||
view.setTag(null);
|
||||
} else {
|
||||
view.setImageEmoji(ReactionEmoji.values()[i].emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,9 +444,14 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
}
|
||||
|
||||
private void handleUpEvent() {
|
||||
hide();
|
||||
if (selected != -1 && onReactionSelectedListener != null) {
|
||||
onReactionSelectedListener.onReactionSelected(messageRecord, ReactionEmoji.values()[selected].emoji);
|
||||
if (selected == customEmojiIndex) {
|
||||
onReactionSelectedListener.onCustomReactionSelected(messageRecord, emojiViews[selected].getTag() != null);
|
||||
} else {
|
||||
onReactionSelectedListener.onReactionSelected(messageRecord, ReactionEmoji.values()[selected].emoji);
|
||||
}
|
||||
} else {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +547,6 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
Animator overlayHideAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_out);
|
||||
overlayHideAnim.setTarget(maskView);
|
||||
overlayHideAnim.setDuration(duration);
|
||||
hides.add(overlayHideAnim);
|
||||
|
||||
Animator backgroundHideAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_out);
|
||||
backgroundHideAnim.setTarget(backgroundView);
|
||||
@@ -511,15 +563,26 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
toolbarHideAnim.setDuration(duration);
|
||||
hides.add(toolbarHideAnim);
|
||||
|
||||
hideAnimatorSet.addListener(new AnimationCompleteListener() {
|
||||
AnimationCompleteListener hideListener = new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
List<Animator> hideAllAnimators = new LinkedList<>(hides);
|
||||
hideAllAnimators.add(overlayHideAnim);
|
||||
|
||||
hideAnimatorSet.addListener(hideListener);
|
||||
hideAnimatorSet.setInterpolator(INTERPOLATOR);
|
||||
hideAnimatorSet.playTogether(hides);
|
||||
hideAnimatorSet.playTogether(hideAllAnimators);
|
||||
|
||||
hideAllButMaskAnimatorSet.setInterpolator(INTERPOLATOR);
|
||||
hideAllButMaskAnimatorSet.playTogether(hides);
|
||||
|
||||
hideMaskAnimatorSet.addListener(hideListener);
|
||||
hideMaskAnimatorSet.setInterpolator(INTERPOLATOR);
|
||||
hideMaskAnimatorSet.playTogether(overlayHideAnim);
|
||||
}
|
||||
|
||||
public interface OnHideListener {
|
||||
@@ -528,6 +591,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
||||
|
||||
public interface OnReactionSelectedListener {
|
||||
void onReactionSelected(@NonNull MessageRecord messageRecord, String emoji);
|
||||
void onCustomReactionSelected(@NonNull MessageRecord messageRecord, boolean hasAddedCustomEmoji);
|
||||
}
|
||||
|
||||
private static class Boundary {
|
||||
|
||||
Reference in New Issue
Block a user