diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 2b14a3ad..60471efd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -1663,6 +1663,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean drawName; private boolean drawNameLayout; private boolean drawNameAvatar; + private boolean drawNameSponsor; + private final android.graphics.RectF nameSponsorRect = new android.graphics.RectF(); private boolean drawTopic; private TopicButton topicButton; @@ -18762,6 +18764,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { currentNameString = ""; } + drawNameSponsor = false; + if (!messageObject.isOutOwner() && currentNameStatus == null && currentNameBotVerificationId == 0 + && currentUser != null && currentUser.id != 0 && messageObject.isFromUser() + && !UserObject.isUserSelf(currentUser) && !currentUser.verified && !currentUser.bot) { + tw.nekomimi.nekogram.helpers.SponsorHelper.requestSponsorStatus(currentUser.id); + drawNameSponsor = tw.nekomimi.nekogram.helpers.SponsorHelper.isKnownSponsor(currentUser.id); + } int additionalWidth = dp(currentMessageObject.isSponsored() ? -24 : 0); CharSequence nameStringFinal = AndroidUtilities.removeDiacritics(currentNameString.replace('\n', ' ').replace('\u200F', ' ')); try { @@ -21910,6 +21919,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_namePaint.setAlpha(oldAlpha); canvas.restore(); + if (drawNameSponsor && viaNameWidth <= 0) { + int sz = dp(15); + float hx = nx + nameOffsetX + nameLayoutWidth + dp(4); + float hy = ny + (nameLayout.getHeight() - sz) / 2f; + nameSponsorRect.set(hx, hy, hx + sz, hy + sz); + tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable.drawStatic(canvas, nameSponsorRect, (int) (0xFF * nameAlpha)); + } + float end; if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { int dWidth = getGroupPhotosWidth(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 27dd120e..a1118fa9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -596,6 +596,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private boolean drawVerified; private boolean drawBotVerified; private boolean drawPremium; + private boolean drawSponsor; + private final android.graphics.RectF sponsorHeartRect = new android.graphics.RectF(); private final View emojiStatusView; private final AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emojiStatus; private final AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable botVerification; @@ -1190,6 +1192,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava drawVerified = false; drawBotVerified = false; drawPremium = false; + drawSponsor = false; drawForwardIcon = false; drawGiftIcon = false; drawScam = 0; @@ -1418,6 +1421,10 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava emojiStatus.setParticles(false, false); } } + if (!drawVerified && !drawPremium && drawScam == 0 && user.id != 0 && !UserObject.isUserSelf(user)) { + tw.nekomimi.nekogram.helpers.SponsorHelper.requestSponsorStatus(user.id); + drawSponsor = tw.nekomimi.nekogram.helpers.SponsorHelper.isKnownSponsor(user.id); + } } if (dialogBotVerificationIcon != 0 && drawBotVerified) { botVerification.set(dialogBotVerificationIcon, false); @@ -2260,6 +2267,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (LocaleController.isRTL) { nameLeft += w; } + } else if (drawSponsor) { + int w = dp(6) + dp(18); + nameWidth -= w; + nameAdditionalsForChannelSubscriber += w; + if (LocaleController.isRTL) { + nameLeft += w; + } } if (drawBotVerified) { nameWidth -= dp(21); @@ -2691,6 +2705,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava nameMutedIconLeft = nameMuteLeft - dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth(); } else if (drawScam != 0) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth()); + } else if (drawSponsor) { + nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - dp(6) - dp(18)); } else { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth()); } @@ -4343,6 +4359,15 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } setDrawableBounds((drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable), nameMuteLeft, y); (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).draw(canvas); + } else if (drawSponsor) { + int y = dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 13.5f : 16.5f); + if ((!(useForceThreeLines || SharedConfig.useThreeLinesLayout) || isForumCell()) && hasTags()) { + y -= dp(9); + } + int sz = dp(18); + int sx = nameMuteLeft - dp(1); + sponsorHeartRect.set(sx, y, sx + sz, y + sz); + tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable.drawStatic(canvas, sponsorHeartRect, 255); } if (drawReorder || reorderIconProgress != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index a822ec8a..882d344f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -74,7 +74,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica private TextView addButton; private ImageView mutualView; private Drawable premiumDrawable; - private final AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable botVerification; + private Drawable sponsorDrawable; private final AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable botVerification; private final AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emojiStatus; private ImageView closeView; protected Theme.ResourcesProvider resourcesProvider; @@ -712,10 +712,21 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica nameTextView.setRightDrawable(premiumDrawable); } nameTextView.setRightDrawableTopPadding(-dp(0.5f)); + } else if (currentUser != null && currentUser.id != 0 && !UserObject.isUserSelf(currentUser) + && !currentUser.verified && !currentUser.bot + && tw.nekomimi.nekogram.helpers.SponsorHelper.isKnownSponsor(currentUser.id)) { + if (sponsorDrawable == null) { + sponsorDrawable = new tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable(dp(16)); + } + nameTextView.setRightDrawable(sponsorDrawable); + nameTextView.setRightDrawableTopPadding(-dp(0.5f)); } else { nameTextView.setRightDrawable(null); nameTextView.setRightDrawableTopPadding(0); } + if (currentUser != null && currentUser.id != 0 && !UserObject.isUserSelf(currentUser) && !currentUser.bot) { + tw.nekomimi.nekogram.helpers.SponsorHelper.requestSponsorStatus(currentUser.id); + } if (currentStatus != null) { statusTextView.setTextColor(statusColor); CharSequence status = currentStatus; @@ -829,6 +840,8 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.emojiLoaded) { nameTextView.invalidate(); + } else if (id == NotificationCenter.sponsorStatusUpdated) { + update(0); } } @@ -836,6 +849,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica protected void onAttachedToWindow() { super.onAttachedToWindow(); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.sponsorStatusUpdated); emojiStatus.attach(); botVerification.attach(); } @@ -844,6 +858,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica protected void onDetachedFromWindow() { super.onDetachedFromWindow(); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.sponsorStatusUpdated); emojiStatus.detach(); botVerification.detach(); storyParams.onDetachFromWindow(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 4254e890..5a98797c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -3204,6 +3204,7 @@ public class ChatActivity extends BaseFragment implements if (themeDelegate.isThemeChangeAvailable(false)) { globalObserversGroup.add(NotificationCenter.needSetDayNightTheme); } + globalObserversGroup.add(NotificationCenter.sponsorStatusUpdated); if (chatInvite != null) { int timeout = chatInvite.expires - getConnectionsManager().getCurrentTime(); @@ -19775,6 +19776,16 @@ public class ChatActivity extends BaseFragment implements avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser))), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), !MessagesController.isSupportUser(currentUser) ? currentUser.emoji_status : null, animated); } } + if (avatarContainer != null) { + boolean sponsor = false; + if (currentChat == null && currentUser != null && !currentUser.self + && !currentUser.verified && !currentUser.scam && !currentUser.fake + && !getMessagesController().isPremiumUser(currentUser)) { + tw.nekomimi.nekogram.helpers.SponsorHelper.requestSponsorStatus(currentUser.id); + sponsor = tw.nekomimi.nekogram.helpers.SponsorHelper.isKnownSponsor(currentUser.id); + } + avatarContainer.setSponsorBadge(sponsor); + } setParentActivityTitle(avatarContainer.getTitleTextView().getText()); updateTitleIcons(); } @@ -20496,6 +20507,15 @@ public class ChatActivity extends BaseFragment implements @Override public void didReceivedNotification(int id, int account, final Object... args) { + if (id == NotificationCenter.sponsorStatusUpdated) { + if (avatarContainer != null) { + updateTitle(false); + } + if (chatListView != null) { + chatListView.invalidateViews(); + } + return; + } if (id == NotificationCenter.messagesDidLoad) { int guid = (Integer) args[10]; if (guid != classGuid) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index 4095c0bb..611aed8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -950,6 +950,36 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent private Drawable verifiedBackground; private Drawable verifiedCheck; + private boolean sponsorBadgeShown; + + /** + * Show/hide the FoxiGram sponsor heart next to the title. Only applied when + * the title has no scam/verified badge in {@code rightDrawable2}. Uses the + * animated {@link tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable} since a + * single header is cheap to animate. + */ + public void setSponsorBadge(boolean show) { + if (show == sponsorBadgeShown) { + return; + } + if (show) { + if (rightDrawableIsScamOrVerified) { + return; // scam/verified takes precedence + } + tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable heart = + new tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable(dp(18)); + titleTextView.setRightDrawable2(heart); + rightDrawable2ContentDescription = getString(R.string.FoxSponsorBadge); + sponsorBadgeShown = true; + } else { + if (sponsorBadgeShown) { + titleTextView.setRightDrawable2(null); + rightDrawable2ContentDescription = null; + } + sponsorBadgeShown = false; + } + } + public void setSubtitle(CharSequence value) { if (lastSubtitle == null) { diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java index 16723676..6facb4b0 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java @@ -72,6 +72,30 @@ public class ShimmerHeartDrawable extends Drawable { return sharedBitmap; } + /** Shared heart artwork, lazily decoded. May be null if decoding failed. */ + public static Bitmap getSharedBitmap() { + return loadBitmap(); + } + + private static final Paint STATIC_PAINT = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + + /** + * Draw the sponsor heart statically (no shimmer) into {@code dst}. Cheap + * enough for list cells and headers that repaint frequently. + */ + public static void drawStatic(@NonNull Canvas canvas, @NonNull RectF dst, int alpha) { + Bitmap bmp = loadBitmap(); + if (bmp == null) { + return; + } + if (alpha < 255) { + STATIC_PAINT.setAlpha(alpha); + } else { + STATIC_PAINT.setAlpha(255); + } + canvas.drawBitmap(bmp, null, dst, STATIC_PAINT); + } + private void buildShine(int w) { // A bright diagonal band, narrow relative to the badge width. shineWidth = Math.max(1, (int) (w * 0.55f)); diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png index 9837feb9..f8a3ff1b 100644 Binary files a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png and b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index 3daff98c..27b0a4e7 100644 Binary files a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png index 3993e997..ab4217be 100644 Binary files a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png and b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_foreground.png index 56f06a53..8dcca269 100644 Binary files a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png index 1479e06c..50b3116e 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png and b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index 4ad5f5b6..7f70ec29 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png index fc490135..e5440db1 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png index d961d1a9..034033ce 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png index f1a59b12..d7ef9d1e 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png index 273cd87b..10d558ed 100644 Binary files a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ