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 60471efd..43734e44 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -21925,6 +21925,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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)); + invalidate(); } float end; 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 a1118fa9..109f1f6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -4368,6 +4368,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava int sx = nameMuteLeft - dp(1); sponsorHeartRect.set(sx, y, sx + sz, y + sz); tw.nekomimi.nekogram.helpers.ShimmerHeartDrawable.drawStatic(canvas, sponsorHeartRect, 255); + invalidate(); } if (drawReorder || reorderIconProgress != 0) { 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 6facb4b0..a2928ac0 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/ShimmerHeartDrawable.java @@ -78,22 +78,65 @@ public class ShimmerHeartDrawable extends Drawable { } private static final Paint STATIC_PAINT = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + private static final Paint STATIC_SHINE_PAINT = new Paint(Paint.ANTI_ALIAS_FLAG); + private static final Paint STATIC_MASK_PAINT = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + private static final Matrix STATIC_SHINE_MATRIX = new Matrix(); + private static LinearGradient staticShineGradient; + private static int staticShineWidth; + + static { + STATIC_MASK_PAINT.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + } /** - * Draw the sponsor heart statically (no shimmer) into {@code dst}. Cheap - * enough for list cells and headers that repaint frequently. + * Draw the sponsor heart with the moving "shimmer" highlight into + * {@code dst}. Used by canvas-drawn cells (chats list, message author + * names, etc.). The host must keep repainting (e.g. invalidate each frame) + * for the highlight to actually move. */ 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); + int w = (int) dst.width(); + if (w <= 0) { + return; } + int wantShine = Math.max(1, (int) (w * 0.55f)); + if (staticShineGradient == null || staticShineWidth != wantShine) { + staticShineWidth = wantShine; + staticShineGradient = new LinearGradient( + 0, 0, staticShineWidth, 0, + new int[]{0x00FFFFFF, 0x00FFFFFF, 0x99FFFFFF, 0x00FFFFFF, 0x00FFFFFF}, + new float[]{0f, 0.35f, 0.5f, 0.65f, 1f}, + Shader.TileMode.CLAMP); + STATIC_SHINE_PAINT.setShader(staticShineGradient); + } + + STATIC_PAINT.setAlpha(alpha < 255 ? alpha : 255); + + int sc = canvas.saveLayer(dst, null); + + // 1) heart artwork canvas.drawBitmap(bmp, null, dst, STATIC_PAINT); + + // 2) moving highlight band, swept diagonally and clipped to artwork alpha + float phase = (System.currentTimeMillis() % CYCLE_MS) / (float) CYCLE_MS; + float travel = dst.width() + staticShineWidth; + float x = dst.left - staticShineWidth + phase * travel; + STATIC_SHINE_MATRIX.reset(); + STATIC_SHINE_MATRIX.postRotate(20f, 0, 0); + STATIC_SHINE_MATRIX.postTranslate(x, dst.top); + staticShineGradient.setLocalMatrix(STATIC_SHINE_MATRIX); + + int ssc = canvas.saveLayer(dst, null); + STATIC_SHINE_PAINT.setAlpha(alpha < 255 ? alpha : 255); + canvas.drawRect(dst, STATIC_SHINE_PAINT); + canvas.drawBitmap(bmp, null, dst, STATIC_MASK_PAINT); + canvas.restoreToCount(ssc); + + canvas.restoreToCount(sc); } private void buildShine(int w) {