Skip to content

Commit

Permalink
Custom Emoji Reactions: Bugfixes (#486)
Browse files Browse the repository at this point in the history
* Update TGMessage.java

* Update BottomSheetViewController.java

* Update ViewPagerTopView.java

* Repainting for custom emoji effect

* Reworking settings for non-bubble mode

* Update TGMessageSticker.java

* Update StickersSuggestionsLayout.java

* Update StickersSuggestionsLayout.java

* Keyboard Fix

* Fixes

* Update TGMessage.java

* Update MessageOptionsPagerController.java

* Update MessageOptionsPagerController.java

---------

Co-authored-by: Vyacheslav <6242627+vkryl@users.noreply.github.com>
  • Loading branch information
Arseny271 and vkryl committed Nov 3, 2023
1 parent f7fd8f7 commit efefce0
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 127 deletions.
Expand Up @@ -21,6 +21,7 @@
import android.graphics.drawable.Drawable;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

Expand All @@ -31,6 +32,7 @@
import org.thunderdog.challegram.loader.ImageReceiver;
import org.thunderdog.challegram.loader.gif.GifFile;
import org.thunderdog.challegram.loader.gif.GifReceiver;
import org.thunderdog.challegram.theme.PorterDuffColorId;
import org.thunderdog.challegram.tool.Drawables;

import me.vkryl.core.lambda.Destroyable;
Expand Down Expand Up @@ -114,6 +116,28 @@ public void setAlpha (int i) {
}
}

public void setThemedPorterDuffColorId (@PorterDuffColorId int colorId) {
gifReceiver.setThemedPorterDuffColorId(colorId);
imageReceiver.setThemedPorterDuffColorId(colorId);
if (drawable != null) {
drawable.setColorFilter(imageReceiver.getBitmapPaint().getColorFilter());
}
}
public void setPorterDuffColorFilter (@ColorInt int color) {
gifReceiver.setPorterDuffColorFilter(color);
imageReceiver.setPorterDuffColorFilter(color);
if (drawable != null) {
drawable.setColorFilter(imageReceiver.getBitmapPaint().getColorFilter());
}
}
public void disablePorterDuffColorFilter () {
gifReceiver.disablePorterDuffColorFilter();
imageReceiver.disablePorterDuffColorFilter();
if (drawable != null) {
drawable.setColorFilter(null);
}
}

@Override
public void setColorFilter (@Nullable ColorFilter colorFilter) {

Expand Down
Expand Up @@ -18,17 +18,20 @@
import android.graphics.Rect;
import android.view.View;

import androidx.annotation.ColorInt;

import org.thunderdog.challegram.charts.CubicBezierInterpolator;
import org.thunderdog.challegram.tool.Paints;
import org.thunderdog.challegram.theme.PorterDuffColorId;
import org.thunderdog.challegram.tool.Screen;
import org.thunderdog.challegram.tool.Views;

import java.util.ArrayList;

import kotlin.random.Random;
import me.vkryl.core.MathUtils;
import me.vkryl.core.lambda.Destroyable;

public class AnimatedEmojiEffect {
public class AnimatedEmojiEffect implements Destroyable {

public AnimatedEmojiDrawable animatedEmojiDrawable;
Rect bounds = new Rect();
Expand All @@ -40,23 +43,23 @@ public class AnimatedEmojiEffect {
boolean longAnimation;
boolean firsDraw = true;

private AnimatedEmojiEffect(AnimatedEmojiDrawable animatedEmojiDrawable, boolean longAnimation) {
private AnimatedEmojiEffect (AnimatedEmojiDrawable animatedEmojiDrawable, boolean longAnimation) {
this.animatedEmojiDrawable = animatedEmojiDrawable;
this.longAnimation = longAnimation;
startTime = System.currentTimeMillis();
}

public static AnimatedEmojiEffect createFrom(AnimatedEmojiDrawable animatedEmojiDrawable, boolean longAnimation) {
public static AnimatedEmojiEffect createFrom (AnimatedEmojiDrawable animatedEmojiDrawable, boolean longAnimation) {
return new AnimatedEmojiEffect(animatedEmojiDrawable, longAnimation);
}

public void setBounds(int l, int t, int r, int b) {
public void setBounds (int l, int t, int r, int b) {
bounds.set(l, t, r, b);
}

long lastGenerateTime;

public void draw(Canvas canvas) {
public void draw (Canvas canvas) {
if (!longAnimation) {
if (firsDraw) {
for (int i = 0; i < 7; i++) {
Expand Down Expand Up @@ -90,19 +93,34 @@ public void draw(Canvas canvas) {
firsDraw = false;
}

public boolean done() {
public boolean done () {
return System.currentTimeMillis() - startTime > 2500;
}

public void setView(View view) {
public void setView (View view) {
animatedEmojiDrawable.attach();
parentView = view;
}

public void removeView() {
public void removeView () {
animatedEmojiDrawable.detach();
}

@Override
public void performDestroy () {
animatedEmojiDrawable.performDestroy();
}

public void setThemedPorterDuffColorId (@PorterDuffColorId int colorId) {
animatedEmojiDrawable.setThemedPorterDuffColorId(colorId);
}
public void setPorterDuffColorFilter (@ColorInt int color) {
animatedEmojiDrawable.setPorterDuffColorFilter(color);
}
public void disablePorterDuffColorFilter () {
animatedEmojiDrawable.disablePorterDuffColorFilter();
}

private class Particle {
float fromX, fromY;
float toX;
Expand All @@ -116,7 +134,7 @@ private class Particle {
boolean mirror;
float randomRotation;

public void generate() {
public void generate () {
progress = 0;
float bestDistance = 0;
float bestX = randX();
Expand Down Expand Up @@ -155,8 +173,6 @@ public void generate() {

fromY = bounds.height() * 0.45f + bounds.height() * 0.1f * (Math.abs(Random.Default.nextInt() % 100) / 100f);



if (longAnimation) {
fromSize = bounds.width() * 0.05f + bounds.width() * 0.1f * (Math.abs(Random.Default.nextInt() % 100) / 100f);
toSize = fromSize * (1.5f + 1.5f * (Math.abs(Random.Default.nextInt() % 100) / 100f));
Expand All @@ -175,23 +191,23 @@ public void generate() {
randomRotation = 20 * ((Random.Default.nextInt() % 100) / 100f);
}

private float randY() {
private float randY () {
return (bounds.height() * 0.5f * (Math.abs(Random.Default.nextInt() % 100) / 100f));
}

private long randDuration() {
private long randDuration () {
return 1000 + Math.abs(Random.Default.nextInt() % 900);
}

private float randX() {
private float randX () {
if (longAnimation) {
return bounds.width() * -0.25f + bounds.width() * 1.5f * (Math.abs(Random.Default.nextInt() % 100) / 100f);
} else {
return bounds.width() * (Math.abs(Random.Default.nextInt() % 100) / 100f);
}
}

public void draw(Canvas canvas) {
public void draw (Canvas canvas) {
progress += (float) Math.min(40, 1000f / Screen.refreshRate()) / duration;
progress = MathUtils.clamp(progress);
float progressInternal = CubicBezierInterpolator.EASE_OUT.getInterpolation(progress);
Expand Down
@@ -0,0 +1,28 @@
/*
* This file is a part of Telegram X
* Copyright © 2014 (tgx-android@pm.me)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* File created on 24/10/2023 at 02:14
*/
package org.thunderdog.challegram.data;

import androidx.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.SOURCE)
@IntDef({
EmojiMessageContentType.NOT_EMOJI, EmojiMessageContentType.ANIMATED_EMOJI, EmojiMessageContentType.NON_BUBBLE_EMOJI
})
public @interface EmojiMessageContentType {
int NOT_EMOJI = 0, ANIMATED_EMOJI = 1, NON_BUBBLE_EMOJI = 2;
}
11 changes: 11 additions & 0 deletions app/src/main/java/org/thunderdog/challegram/data/TD.java
Expand Up @@ -5442,4 +5442,15 @@ public static boolean hasCustomEmoji (TdApi.FormattedText text) {

return false;
}

public static boolean isStickerFromAnimatedEmojiPack (@Nullable TdApi.MessageContent content) {
if (content == null || content.getConstructor() != TdApi.MessageAnimatedEmoji.CONSTRUCTOR) {
return false;
}
return isStickerFromAnimatedEmojiPack(((TdApi.MessageAnimatedEmoji) content).animatedEmoji.sticker);
}

public static boolean isStickerFromAnimatedEmojiPack (@Nullable TdApi.Sticker sticker) {
return sticker != null && sticker.setId == TdConstants.TELEGRAM_ANIMATED_EMOJI_STICKER_SET_ID;
}
}
75 changes: 68 additions & 7 deletions app/src/main/java/org/thunderdog/challegram/data/TGMessage.java
Expand Up @@ -157,6 +157,7 @@
import me.vkryl.td.ChatId;
import me.vkryl.td.MessageId;
import me.vkryl.td.Td;
import me.vkryl.td.TdConstants;

public abstract class TGMessage implements InvalidateContentProvider, TdlibDelegate, FactorAnimator.Target, Comparable<TGMessage>, Counter.Callback, TGAvatars.Callback, TranslationsManager.Translatable {
private static final int MAXIMUM_CHANNEL_MERGE_TIME_DIFF = 150;
Expand Down Expand Up @@ -2009,7 +2010,8 @@ public final void draw (MessageView view, Canvas c, @NonNull AvatarReceiver avat
hAuthorEmojiStatus.draw(c, left + hAuthorNameT.getWidth() + Screen.dp(3), newTop, 1f, view.getEmojiStatusReceiver());
}
if (sender.hasChatMark() && hAuthorChatMark != null) {
int cmLeft = left + hAuthorNameT.getWidth() + Screen.dp(6f);
int cmLeft = left + hAuthorNameT.getWidth() + Screen.dp(3f)
+ (hAuthorEmojiStatus != null ? hAuthorEmojiStatus.getWidth(Screen.dp(3)) : 0);
RectF rct = Paints.getRectF();
rct.set(cmLeft, newTop, cmLeft + hAuthorChatMark.getWidth() + Screen.dp(8f), newTop + hAuthorNameT.getLineHeight(false));
c.drawRoundRect(rct, Screen.dp(2f), Screen.dp(2f), Paints.getProgressPaint(Theme.getColor(ColorId.textNegative), Screen.dp(1.5f)));
Expand Down Expand Up @@ -7661,11 +7663,38 @@ public static TGMessage valueOf (MessagesManager context, TdApi.Message msg) {
}

@Nullable
private static TGMessage checkPendingContent (MessagesManager context, TdApi.Message msg, TdApi.MessageContent oldContent, @Nullable TdApi.MessageContent pendingContent, boolean allowCustomEmoji) {
if (pendingContent == null) {
private static TGMessage checkPendingContent (MessagesManager context, TdApi.Message msg, TdApi.MessageContent oldContent, @Nullable TdApi.MessageContent pendingContent, boolean allowAnimatedEmoji, boolean allowNonBubbleEmoji) {
if (pendingContent == null || oldContent.getConstructor() != TdApi.MessageAnimatedEmoji.CONSTRUCTOR && oldContent.getConstructor() != TdApi.MessageText.CONSTRUCTOR) {
return null;
}

final @EmojiMessageContentType int emojiPendingContentType = getEmojiMessageContentType(pendingContent, allowAnimatedEmoji, allowNonBubbleEmoji);
if (emojiPendingContentType == EmojiMessageContentType.NOT_EMOJI) {
final TdApi.MessageText oldMessageText;
if (oldContent.getConstructor() == TdApi.MessageAnimatedEmoji.CONSTRUCTOR) {
TdApi.MessageAnimatedEmoji oldEmoji = nonNull((TdApi.MessageAnimatedEmoji) oldContent);
oldMessageText = new TdApi.MessageText(Td.textOrCaption(oldEmoji), null);
} else if (oldContent.getConstructor() == TdApi.MessageText.CONSTRUCTOR) {
oldMessageText = nonNull((TdApi.MessageText) oldContent);
} else {
throw new IllegalArgumentException("Wrong content type");
}

final TdApi.MessageText newMessageText;
if (pendingContent.getConstructor() == TdApi.MessageAnimatedEmoji.CONSTRUCTOR) {
TdApi.MessageAnimatedEmoji newEmoji = nonNull((TdApi.MessageAnimatedEmoji) pendingContent);
newMessageText = new TdApi.MessageText(Td.textOrCaption(newEmoji), null);
} else if (pendingContent.getConstructor() == TdApi.MessageText.CONSTRUCTOR) {
newMessageText = (TdApi.MessageText) pendingContent;
} else {
throw new IllegalArgumentException("Wrong content type");
}

return new TGMessageText(context, msg, oldMessageText, newMessageText);
} else {
return new TGMessageSticker(context, msg, oldContent, pendingContent);
}
/*
final TdApi.MessageText pendingMessageText = pendingContent.getConstructor() == TdApi.MessageText.CONSTRUCTOR ?
((TdApi.MessageText) pendingContent) : null;
final TdApi.MessageAnimatedEmoji pendingMessageEmoji = pendingContent.getConstructor() == TdApi.MessageAnimatedEmoji.CONSTRUCTOR ?
Expand All @@ -7690,6 +7719,7 @@ private static TGMessage checkPendingContent (MessagesManager context, TdApi.Mes
}
return null;
*/
}

public static TGMessage valueOf (MessagesManager context, TdApi.Message msg, TdApi.MessageContent content) {
Expand All @@ -7711,26 +7741,27 @@ public static TGMessage valueOf (MessagesManager context, TdApi.Message msg, TdA

int unsupportedStringRes = R.string.UnsupportedMessage;

final boolean allowEmoji = !Settings.instance().getNewSetting(Settings.SETTING_FLAG_NO_ANIMATED_EMOJI);
final boolean allowAnimatedEmoji = !Settings.instance().getNewSetting(Settings.SETTING_FLAG_NO_ANIMATED_EMOJI);
final boolean allowNonBubbleEmoji = Settings.instance().useBigEmoji();
final TdApi.MessageContent pendingContent = tdlib.getPendingMessageText(msg.chatId, msg.id);

TGMessage message = checkPendingContent(context, msg, content, pendingContent, allowEmoji);
TGMessage message = checkPendingContent(context, msg, content, pendingContent, allowAnimatedEmoji, allowNonBubbleEmoji);
if (message != null) {
return message;
}

switch (content.getConstructor()) {
case TdApi.MessageAnimatedEmoji.CONSTRUCTOR: {
TdApi.MessageAnimatedEmoji emoji = nonNull((TdApi.MessageAnimatedEmoji) content);
if (!allowEmoji) {
if (getEmojiMessageContentType(content, allowAnimatedEmoji, allowNonBubbleEmoji) == EmojiMessageContentType.NOT_EMOJI) {
return new TGMessageText(context, msg, new TdApi.MessageText(Td.textOrCaption(emoji), null), null);
} else {
return new TGMessageSticker(context, msg, emoji, null);
}
}
case TdApi.MessageText.CONSTRUCTOR: {
TdApi.MessageText messageText = nonNull((TdApi.MessageText) content);
if (allowEmoji && NonBubbleEmojiLayout.isValidEmojiText(messageText.text)) {
if (getEmojiMessageContentType(content, allowAnimatedEmoji, allowNonBubbleEmoji) != EmojiMessageContentType.NOT_EMOJI) {
return new TGMessageSticker(context, msg, messageText, null);
}
return new TGMessageText(context, msg, nonNull((TdApi.MessageText) content), null);
Expand Down Expand Up @@ -8498,6 +8529,7 @@ private void startSetReactionAnimationIfReady () {
new ReactionsOverlayView.ReactionInfo(context().reactionsOverlayManager())
.setSticker(nextSetReactionAnimation.reaction.staticCenterAnimationSicker(), false)
.setAnimationEndListener(this::onQuickReactionAnimationFinish)
.setRepaintingColorIds(ColorId.text, ColorId.text)
.setAnimatedPosition(
new Point(startX, startY),
new Point(finishX, finishY),
Expand All @@ -8515,6 +8547,7 @@ private void startSetReactionAnimationIfReady () {
new ReactionsOverlayView.ReactionInfo(context().reactionsOverlayManager())
.setSticker(nextSetReactionAnimation.reaction.staticCenterAnimationSicker(), false)
.setAnimationEndListener(this::onQuickReactionAnimationFinish)
.setRepaintingColorIds(ColorId.text, ColorId.text)
.setAnimatedPosition(
new Point(startX, startY),
new Point(finishX, finishY),
Expand Down Expand Up @@ -8636,6 +8669,7 @@ public void startReactionBubbleAnimation (TdApi.ReactionType reactionType) {
context().reactionsOverlayManager().addOverlay(
new ReactionsOverlayView.ReactionInfo(context().reactionsOverlayManager())
.setSticker(overlaySticker, true)
.setRepaintingColorIds(ColorId.text, ColorId.text)
.setUseDefaultSprayAnimation(tgReaction.isCustom())
.setEmojiStatusEffect(tgReaction.isCustom() ? tgReaction.newCenterAnimationSicker() : null)
.setPosition(new Point(bubbleX, bubbleY), Screen.dp(90))
Expand Down Expand Up @@ -9190,4 +9224,31 @@ public String getSponsoredMessageUrl () {

return null;
}

/* * */

public static @EmojiMessageContentType int getEmojiMessageContentType (TdApi.MessageContent content) {
final boolean allowAnimatedEmoji = !Settings.instance().getNewSetting(Settings.SETTING_FLAG_NO_ANIMATED_EMOJI);
final boolean allowNonBubbleEmoji = Settings.instance().useBigEmoji();
return getEmojiMessageContentType(content, allowAnimatedEmoji, allowNonBubbleEmoji);
}

public static @EmojiMessageContentType int getEmojiMessageContentType (TdApi.MessageContent content, boolean allowAnimatedEmoji, boolean allowNonBubbleEmoji) {
if (content == null) {
return EmojiMessageContentType.NOT_EMOJI;
}

if (content.getConstructor() == TdApi.MessageAnimatedEmoji.CONSTRUCTOR) {
if (allowAnimatedEmoji && TD.isStickerFromAnimatedEmojiPack(content)) {
return EmojiMessageContentType.ANIMATED_EMOJI;
} else if (allowNonBubbleEmoji) {
return EmojiMessageContentType.NON_BUBBLE_EMOJI;
}
} else if (content.getConstructor() == TdApi.MessageText.CONSTRUCTOR) {
if (allowNonBubbleEmoji && NonBubbleEmojiLayout.isValidEmojiText(((TdApi.MessageText) content).text)) {
return EmojiMessageContentType.NON_BUBBLE_EMOJI;
}
}
return EmojiMessageContentType.NOT_EMOJI;
}
}

0 comments on commit efefce0

Please sign in to comment.