diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 0651dd8bf8..b21266ec7c 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -368,22 +368,25 @@ public boolean updateQueuedPeriods( newPeriodInfo.copyWithRequestedContentPositionUs( oldPeriodInfo.requestedContentPositionUs); - if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) { - // The period duration changed. Remove all subsequent periods and check whether we read - // beyond the new duration. - periodHolder.updateClipping(); - long newDurationInRendererTime = - newPeriodInfo.durationUs == C.TIME_UNSET - ? Long.MAX_VALUE - : periodHolder.toRendererTime(newPeriodInfo.durationUs); - boolean isReadingAndReadBeyondNewDuration = - periodHolder == reading - && !periodHolder.info.isFollowedByTransitionToSameStream - && (maxRendererReadPositionUs == C.TIME_END_OF_SOURCE - || maxRendererReadPositionUs >= newDurationInRendererTime); - boolean readingPeriodRemoved = removeAfter(periodHolder); - return !readingPeriodRemoved && !isReadingAndReadBeyondNewDuration; - } + //@xaxtix + //comment cause lead to infinit seek loop in end of video + +// if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) { +// // The period duration changed. Remove all subsequent periods and check whether we read +// // beyond the new duration. +// periodHolder.updateClipping(); +// long newDurationInRendererTime = +// newPeriodInfo.durationUs == C.TIME_UNSET +// ? Long.MAX_VALUE +// : periodHolder.toRendererTime(newPeriodInfo.durationUs); +// boolean isReadingAndReadBeyondNewDuration = +// periodHolder == reading +// && !periodHolder.info.isFollowedByTransitionToSameStream +// && (maxRendererReadPositionUs == C.TIME_END_OF_SOURCE +// || maxRendererReadPositionUs >= newDurationInRendererTime); +// boolean readingPeriodRemoved = removeAfter(periodHolder); +// return !readingPeriodRemoved && !isReadingAndReadBeyondNewDuration; +// } previousPeriodHolder = periodHolder; periodHolder = periodHolder.getNext(); diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java index 8156563954..f9d991e721 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java @@ -97,19 +97,19 @@ public void experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boole @Override public MediaCodecAdapter createAdapter(MediaCodecAdapter.Configuration configuration) throws IOException { -// if (Util.SDK_INT >= 23 -// && (asynchronousMode == MODE_ENABLED -// || (asynchronousMode == MODE_DEFAULT && Util.SDK_INT >= 31))) { -// int trackType = MimeTypes.getTrackType(configuration.format.sampleMimeType); -// Log.i( -// TAG, -// "Creating an asynchronous MediaCodec adapter for track type " -// + Util.getTrackTypeString(trackType)); -// AsynchronousMediaCodecAdapter.Factory factory = -// new AsynchronousMediaCodecAdapter.Factory( -// trackType, enableSynchronizeCodecInteractionsWithQueueing); -// return factory.createAdapter(configuration); -// } + if (Util.SDK_INT >= 23 + && (asynchronousMode == MODE_ENABLED + || (asynchronousMode == MODE_DEFAULT && Util.SDK_INT >= 31))) { + int trackType = MimeTypes.getTrackType(configuration.format.sampleMimeType); + Log.i( + TAG, + "Creating an asynchronous MediaCodec adapter for track type " + + Util.getTrackTypeString(trackType)); + AsynchronousMediaCodecAdapter.Factory factory = + new AsynchronousMediaCodecAdapter.Factory( + trackType, enableSynchronizeCodecInteractionsWithQueueing); + return factory.createAdapter(configuration); + } return new SynchronousMediaCodecAdapter.Factory().createAdapter(configuration); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 5c23d442f4..2a9849f912 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -174,6 +174,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.IDN; @@ -247,9 +248,6 @@ public class AndroidUtilities { private static int adjustOwnerClassGuid = 0; private static int altFocusableClassGuid = 0; - private static Paint roundPaint; - private static RectF bitmapRect; - public static final RectF rectTmp = new RectF(); public static final Rect rectTmp2 = new Rect(); @@ -513,9 +511,17 @@ public static void recycleBitmaps(List bitmapToRecycle) { return; } if (bitmapToRecycle != null && !bitmapToRecycle.isEmpty()) { + ArrayList> bitmapsToRecycleRef = new ArrayList<>(); + for (int i = 0; i < bitmapToRecycle.size(); i++) { + Bitmap bitmap = bitmapToRecycle.get(i); + if (bitmap != null && !bitmap.isRecycled()) { + bitmapsToRecycleRef.add(new WeakReference<>(bitmap)); + } + } AndroidUtilities.runOnUIThread(() -> Utilities.globalQueue.postRunnable(() -> { - for (int i = 0; i < bitmapToRecycle.size(); i++) { - Bitmap bitmap = bitmapToRecycle.get(i); + for (int i = 0; i < bitmapsToRecycleRef.size(); i++) { + Bitmap bitmap = bitmapsToRecycleRef.get(i).get(); + bitmapsToRecycleRef.get(i).clear(); if (bitmap != null && !bitmap.isRecycled()) { try { bitmap.recycle(); @@ -3202,10 +3208,10 @@ public static File generateVideoPath(boolean secretChat) { } public static String formatFileSize(long size) { - return formatFileSize(size, false); + return formatFileSize(size, false, false); } - public static String formatFileSize(long size, boolean removeZero) { + public static String formatFileSize(long size, boolean removeZero, boolean makeShort) { if (size == 0) { return String.format("%d KB", 0); } else if (size < 1024) { @@ -3228,6 +3234,8 @@ public static String formatFileSize(long size, boolean removeZero) { float value = (int) (size / 1024L / 1024L) / 1000.0f; if (removeZero && (value - (int) value) * 10 == 0) { return String.format("%d GB", (int) value); + } else if (makeShort) { + return String.format("%.1f GB", value); } else { return String.format("%.2f GB", value); } @@ -5370,10 +5378,12 @@ public static ByteBuffer cloneByteBuffer(ByteBuffer original) { System.gc(); clone = ByteBuffer.allocate(original.capacity()); } + int position = original.position(); original.rewind(); clone.put(original); original.rewind(); clone.flip(); + clone.position(position); return clone; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 5bd738ddfe..6c9ff9cf54 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -24,8 +24,8 @@ public class BuildVars { public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29; - public static int BUILD_VERSION = 3712; - public static String BUILD_VERSION_STRING = "9.7.4"; + public static int BUILD_VERSION = 3721; + public static String BUILD_VERSION_STRING = "9.7.6"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessageSharedResources.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessageSharedResources.java new file mode 100644 index 0000000000..72e85a460b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessageSharedResources.java @@ -0,0 +1,32 @@ +package org.telegram.messenger; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; + +public class ChatMessageSharedResources { + + public Context context; + public Drawable chat_msgAvatarLiveLocationDrawable; + public Drawable chat_redLocationIcon; + + public ChatMessageSharedResources(Context context) { + this.context = context; + } + + public Drawable getRedLocationIcon() { + if (chat_redLocationIcon == null) { + Resources resources = context.getResources(); + chat_redLocationIcon = resources.getDrawable(R.drawable.map_pin).mutate(); + } + return chat_redLocationIcon; + } + + public Drawable getAvatarLiveLocation() { + if (chat_msgAvatarLiveLocationDrawable == null) { + Resources resources = context.getResources(); + chat_msgAvatarLiveLocationDrawable = resources.getDrawable(R.drawable.livepin).mutate(); + } + return chat_msgAvatarLiveLocationDrawable; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index 9856334c16..f118c0e924 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -25,7 +25,7 @@ public class DispatchQueue extends Thread { private long lastTaskTime; private static int indexPointer = 0; public final int index = indexPointer++; - private int priority = THREAD_PRIORITY_DEFAULT; + private int threadPriority = THREAD_PRIORITY_DEFAULT; public DispatchQueue(final String threadName) { this(threadName, true); @@ -39,7 +39,7 @@ public DispatchQueue(final String threadName, boolean start) { } public DispatchQueue(final String threadName, boolean start, int priority) { - this.priority = priority; + this.threadPriority = priority; setName(threadName); if (start) { start(); @@ -126,8 +126,8 @@ public void run() { return true; }); syncLatch.countDown(); - if (priority != THREAD_PRIORITY_DEFAULT) { - Process.setThreadPriority(priority); + if (threadPriority != THREAD_PRIORITY_DEFAULT) { + Process.setThreadPriority(threadPriority); } Looper.loop(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 5a13138607..8ac61b73c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -708,7 +708,12 @@ protected long[] getDownloadedLengthFromOffset(final long offset, final long len final CountDownLatch countDownLatch = new CountDownLatch(1); final long[] result = new long[2]; Utilities.stageQueue.postRunnable(() -> { - result[0] = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, offset, length); + try { + result[0] = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, offset, length); + } catch (Throwable e) { + FileLog.e(e); + result[0] = 0; + } if (state == stateFinished) { result[1] = 1; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 278a4cd567..a6e3b6ee8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -165,6 +165,7 @@ private static void checkGson() { privateFields.add("networkType"); privateFields.add("disableFree"); privateFields.add("mContext"); + privateFields.add("priority"); //exclude file loading excludeRequests = new HashSet<>(); @@ -183,7 +184,7 @@ public boolean shouldSkipField(FieldAttributes f) { @Override public boolean shouldSkipClass(Class clazz) { - return clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class); + return clazz.isInstance(DispatchQueue.class) || clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class); } }; gson = new GsonBuilder().addSerializationExclusionStrategy(strategy).registerTypeAdapterFactory(RuntimeClassNameTypeAdapterFactory.of(TLObject.class, "type_", strategy)).create(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index 61ea8111da..18f019fc4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -71,6 +71,7 @@ public static int getStreamPrioriy(TLRPC.Document document) { @Override public long open(DataSpec dataSpec) throws IOException { uri = dataSpec.uri; + transferInitializing(dataSpec); currentAccount = Utilities.parseInt(uri.getQueryParameter("account")); parentObject = FileLoader.getInstance(currentAccount).getParentObject(Utilities.parseInt(uri.getQueryParameter("rid"))); document = new TLRPC.TL_document(); @@ -124,6 +125,7 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { return C.RESULT_END_OF_INPUT; } else { int availableLength = 0; + int bytesRead; try { if (bytesRemaining < readLength) { readLength = (int) bytesRemaining; @@ -165,14 +167,16 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { if (!opened) { return 0; } - file.readFully(buffer, offset, availableLength); - currentOffset += availableLength; - bytesRemaining -= availableLength; - bytesTransferred(availableLength); + bytesRead = file.read(buffer, offset, availableLength); + if (bytesRead > 0) { + currentOffset += bytesRead; + bytesRemaining -= bytesRead; + bytesTransferred(bytesRead); + } } catch (Exception e) { throw new IOException(e); } - return availableLength; + return bytesRead; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 6a8df8621d..e0e3530d1d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -52,7 +52,6 @@ import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.Point; import org.telegram.ui.Components.RLottieDrawable; -import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.Components.SlotsDrawable; import org.telegram.ui.Components.ThemePreviewDrawable; @@ -103,6 +102,8 @@ */ public class ImageLoader { + private static final boolean DEBUG_MODE = false; + private HashMap bitmapUseCounts = new HashMap<>(); private LruCache smallImagesMemCache; private LruCache memCache; @@ -1822,7 +1823,9 @@ public static Bitmap getStrippedPhotoBitmap(byte[] photoBytes, String filter) { data[164] = photoBytes[1]; data[166] = photoBytes[2]; - Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, len); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = SharedConfig.deviceIsHigh() ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, len, options); if (bitmap != null && !TextUtils.isEmpty(filter) && filter.contains("b")) { Utilities.blurBitmap(bitmap, 3, 1, bitmap.getWidth(), bitmap.getHeight(), bitmap.getRowBytes()); } @@ -2060,15 +2063,15 @@ public ImageLoader() { } else { maxSize = 15; } - int cacheSize = Math.min(maxSize, memoryClass / 7) * 1024 * 1024; + int cacheSize = DEBUG_MODE ? 1 : Math.min(maxSize, memoryClass / 7) * 1024 * 1024; - int commonCacheSize = (int) (cacheSize * 0.8f); - int smallImagesCacheSize = (int) (cacheSize * 0.2f); + int commonCacheSize = DEBUG_MODE ? 1 : (int) (cacheSize * 0.8f); + int smallImagesCacheSize = DEBUG_MODE ? 1 : (int) (cacheSize * 0.2f); memCache = new LruCache(commonCacheSize) { @Override protected int sizeOf(String key, BitmapDrawable value) { - return value.getBitmap().getByteCount(); + return sizeOfBitmapDrawable(value); } @Override @@ -2090,7 +2093,7 @@ protected void entryRemoved(boolean evicted, String key, final BitmapDrawable ol smallImagesMemCache = new LruCache(smallImagesCacheSize) { @Override protected int sizeOf(String key, BitmapDrawable value) { - return value.getBitmap().getByteCount(); + return sizeOfBitmapDrawable(value); } @Override @@ -2109,18 +2112,18 @@ protected void entryRemoved(boolean evicted, String key, final BitmapDrawable ol } } }; - wallpaperMemCache = new LruCache(cacheSize / 4) { + wallpaperMemCache = new LruCache(DEBUG_MODE ? 1 : cacheSize / 4) { @Override protected int sizeOf(String key, BitmapDrawable value) { - return value.getBitmap().getByteCount(); + return sizeOfBitmapDrawable(value); } }; - lottieMemCache = new LruCache(512 * 512 * 2 * 4 * 5) { + lottieMemCache = new LruCache(DEBUG_MODE ? 1 : 512 * 512 * 2 * 4 * 5) { @Override protected int sizeOf(String key, BitmapDrawable value) { - return value.getIntrinsicWidth() * value.getIntrinsicHeight() * 4 * 2; + return sizeOfBitmapDrawable(value); } @Override @@ -2327,6 +2330,18 @@ public void onReceive(Context arg0, Intent intent) { checkMediaPaths(); } + private int sizeOfBitmapDrawable(BitmapDrawable value) { + if (value instanceof AnimatedFileDrawable) { + AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) value; + int maxSize = animatedFileDrawable.getRenderingHeight() * animatedFileDrawable.getRenderingWidth() * 4 * 3; + maxSize = Math.max(animatedFileDrawable.getIntrinsicHeight() * value.getIntrinsicWidth() * 4 * 3, maxSize); + return maxSize; + } if (value instanceof RLottieDrawable) { + return value.getIntrinsicWidth() * value.getIntrinsicHeight() * 4 * 2; + } + return value.getBitmap().getByteCount(); + } + public void checkMediaPaths() { checkMediaPaths(null); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 7c0ffe9e28..9b48fddca0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -12,6 +12,7 @@ import android.graphics.BitmapShader; import android.graphics.BlendMode; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.ComposeShader; import android.graphics.Matrix; @@ -49,13 +50,15 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { List preloadReceivers; + private boolean allowCrossfadeWithImage = true; + public boolean updateThumbShaderMatrix() { if (currentThumbDrawable != null && thumbShader != null) { drawDrawable(null, currentThumbDrawable, 255, thumbShader, 0, 0, 0, null); return true; } - if (staticThumbDrawable != null && thumbShader != null) { - drawDrawable(null, staticThumbDrawable, 255, thumbShader, 0, 0, 0, null); + if (staticThumbDrawable != null && staticThumbShader != null) { + drawDrawable(null, staticThumbDrawable, 255, staticThumbShader, 0, 0, 0, null); return true; } return false; @@ -239,6 +242,7 @@ private void clear() { private int thumbTag; private Drawable currentThumbDrawable; public BitmapShader thumbShader; + public BitmapShader staticThumbShader; private int thumbOrientation, thumbInvert; private ImageLocation currentMediaLocation; @@ -284,21 +288,20 @@ private void clear() { private float imageX, imageY, imageW, imageH; private float sideClip; - private RectF drawRegion = new RectF(); + private final RectF drawRegion = new RectF(); private boolean isVisible = true; private boolean isAspectFit; private boolean forcePreview; private boolean forceCrossfade; - private int[] roundRadius = new int[4]; + private final int[] roundRadius = new int[4]; private boolean isRoundRect = true; private Object mark; private Paint roundPaint; - private RectF roundRect = new RectF(); - private RectF bitmapRect = new RectF(); - private Matrix shaderMatrix = new Matrix(); - private Path roundPath = new Path(); - private static float[] radii = new float[8]; + private final RectF roundRect = new RectF(); + private final Matrix shaderMatrix = new Matrix(); + private final Path roundPath = new Path(); + private static final float[] radii = new float[8]; private float overrideAlpha = 1.0f; private int isPressed; private boolean centerRotation; @@ -661,7 +664,7 @@ public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocat recycleBitmap(thumbKey, TYPE_THUMB); recycleBitmap(null, TYPE_CROSSFDADE); recycleBitmap(mediaKey, TYPE_MEDIA); - crossfadeShader = thumbShader; + crossfadeShader = staticThumbShader; crossfadeImage = staticThumbDrawable; crossfadingWithThumb = false; crossfadeKey = null; @@ -700,6 +703,7 @@ public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocat imageShader = null; composeShader = null; thumbShader = null; + staticThumbShader = null; mediaShader = null; legacyShader = null; legacyCanvas = null; @@ -819,7 +823,7 @@ public void setImageBitmap(Drawable bitmap) { recycleBitmap(null, TYPE_THUMB); recycleBitmap(null, TYPE_CROSSFDADE); recycleBitmap(null, TYPE_MEDIA); - crossfadeShader = thumbShader; + crossfadeShader = staticThumbShader; crossfadeImage = staticThumbDrawable; crossfadingWithThumb = true; crossfadeKey = null; @@ -863,6 +867,7 @@ public void setImageBitmap(Drawable bitmap) { } fileDrawable.setAllowDecodeSingleFrame(true); } + staticThumbShader = null; thumbShader = null; roundPaint.setShader(null); setStaticDrawable(bitmap); @@ -937,8 +942,10 @@ private void setStaticDrawable(Drawable bitmap) { } private void setDrawableShader(Drawable drawable, BitmapShader shader) { - if (drawable == currentThumbDrawable || drawable == staticThumbDrawable) { + if (drawable == currentThumbDrawable) { thumbShader = shader; + } else if (drawable == staticThumbDrawable) { + staticThumbShader = shader; } else if (drawable == currentMediaDrawable) { mediaShader = shader; } else if (drawable == currentImageDrawable) { @@ -1040,10 +1047,10 @@ public void onDetachedFromWindow() { if (staticThumbDrawable != null) { setStaticDrawable(null); - thumbShader = null; - roundPaint.setShader(null); + staticThumbShader = null; } clearImage(); + roundPaint.setShader(null); if (isPressed == 0) { pressedProgress = 0f; } @@ -1768,23 +1775,6 @@ public void skipDraw() { // lottieDrawable.updateCurrentFrame(); // } } - - protected boolean customDraw( - Canvas canvas, - AnimatedFileDrawable animation, - RLottieDrawable lottieAnimation, - Drawable currentMediaDrawable, BitmapShader currentMediaShader, - Drawable currentImageDrawable, BitmapShader currentImageShader, - Drawable currentThumbDrawable, BitmapShader currentThumbShader, - boolean crossfadeWithOldImage, boolean crossfadingWithThumb, - Drawable crossfadeImage, BitmapShader crossfadeShader, - Drawable staticThumbDrawable, - float currentAlpha, float previousAlpha, float overrideAlpha, - int[] roundRadius, - BackgroundThreadDrawHolder backgroundThreadDrawHolder - ) { - return false; - } public boolean draw(Canvas canvas) { return draw(canvas, null); @@ -1807,6 +1797,7 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr BitmapShader imageShader; Drawable currentThumbDrawable; BitmapShader thumbShader; + BitmapShader staticThumbShader; boolean crossfadeWithOldImage; boolean crossfadingWithThumb; @@ -1830,6 +1821,7 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr currentImageDrawable = backgroundThreadDrawHolder.imageDrawable; imageShader = backgroundThreadDrawHolder.imageShader; thumbShader = backgroundThreadDrawHolder.thumbShader; + staticThumbShader = backgroundThreadDrawHolder.staticThumbShader; crossfadeImage = backgroundThreadDrawHolder.crossfadeImage; crossfadeWithOldImage = backgroundThreadDrawHolder.crossfadeWithOldImage; crossfadingWithThumb = backgroundThreadDrawHolder.crossfadingWithThumb; @@ -1851,6 +1843,7 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr imageShader = this.imageShader; currentThumbDrawable = this.currentThumbDrawable; thumbShader = this.thumbShader; + staticThumbShader = this.staticThumbShader; crossfadeWithOldImage = this.crossfadeWithOldImage; crossfadingWithThumb = this.crossfadingWithThumb; crossfadeImage = this.crossfadeImage; @@ -1862,21 +1855,6 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr animationNotReady = animation != null && !animation.hasBitmap() || lottieDrawable != null && !lottieDrawable.hasBitmap(); colorFilter = this.colorFilter; } - - if (customDraw( - canvas, - animation, lottieDrawable, - currentMediaDrawable, mediaShader, - currentImageDrawable, imageShader, - currentThumbDrawable, thumbShader, - crossfadeWithOldImage, crossfadingWithThumb, - crossfadeImage, crossfadeShader, - staticThumbDrawable, - currentAlpha, previousAlpha, overrideAlpha, - roundRadius, backgroundThreadDrawHolder - )) { - return true; - } if (animation != null) { animation.setRoundRadius(roundRadius); @@ -1908,18 +1886,18 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr shaderToUse = crossfadeShader; orientation = imageOrientation; invert = imageInvert; + } else if (currentThumbDrawable != null) { + drawable = currentThumbDrawable; + shaderToUse = thumbShader; + orientation = thumbOrientation; + invert = thumbInvert; } else if (staticThumbDrawable instanceof BitmapDrawable) { drawable = staticThumbDrawable; - if (useRoundForThumb && thumbShader == null) { + if (useRoundForThumb && staticThumbShader == null) { updateDrawableRadius(staticThumbDrawable); - thumbShader = this.thumbShader; + staticThumbShader = this.staticThumbShader; } - shaderToUse = thumbShader; - orientation = thumbOrientation; - invert = thumbInvert; - } else if (currentThumbDrawable != null) { - drawable = currentThumbDrawable; - shaderToUse = thumbShader; + shaderToUse = staticThumbShader; orientation = thumbOrientation; invert = thumbInvert; } @@ -1932,17 +1910,17 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr if (drawable != null) { if (crossfadeAlpha != 0) { if (previousAlpha != 1f && (drawable == currentImageDrawable || drawable == currentMediaDrawable) && staticThumbDrawable != null) { - if (useRoundForThumb && thumbShader == null) { + if (useRoundForThumb && staticThumbShader == null) { updateDrawableRadius(staticThumbDrawable); - thumbShader = this.thumbShader; + staticThumbShader = this.staticThumbShader; } - drawDrawable(canvas, staticThumbDrawable, (int) (overrideAlpha * 255), thumbShader, orientation, invert, backgroundThreadDrawHolder); + drawDrawable(canvas, staticThumbDrawable, (int) (overrideAlpha * 255), staticThumbShader, orientation, invert, backgroundThreadDrawHolder); } if (crossfadeWithThumb && animationNotReady) { drawDrawable(canvas, drawable, (int) (overrideAlpha * 255), shaderToUse, orientation, invert, backgroundThreadDrawHolder); } else { + Drawable thumbDrawable = null; if (crossfadeWithThumb && currentAlpha != 1.0f) { - Drawable thumbDrawable = null; BitmapShader thumbShaderToUse = null; if (drawable == currentImageDrawable || drawable == currentMediaDrawable) { if (crossfadeImage != null) { @@ -1953,20 +1931,20 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr thumbShaderToUse = thumbShader; } else if (staticThumbDrawable != null) { thumbDrawable = staticThumbDrawable; - if (useRoundForThumb && thumbShader == null) { + if (useRoundForThumb && staticThumbShader == null) { updateDrawableRadius(staticThumbDrawable); - thumbShader = this.thumbShader; + staticThumbShader = this.staticThumbShader; } - thumbShaderToUse = thumbShader; + thumbShaderToUse = staticThumbShader; } } else if (drawable == currentThumbDrawable || drawable == crossfadeImage) { if (staticThumbDrawable != null) { thumbDrawable = staticThumbDrawable; - if (useRoundForThumb && thumbShader == null) { + if (useRoundForThumb && staticThumbShader == null) { updateDrawableRadius(staticThumbDrawable); - thumbShader = this.thumbShader; + staticThumbShader = this.staticThumbShader; } - thumbShaderToUse = thumbShader; + thumbShaderToUse = staticThumbShader; } } else if (drawable == staticThumbDrawable) { if (crossfadeImage != null) { @@ -3019,6 +2997,7 @@ public void startCrossfadeFromStaticThumb(Drawable thumb) { currentThumbKey = null; currentThumbDrawable = null; thumbShader = null; + staticThumbShader = null; roundPaint.setShader(null); setStaticDrawable(thumb); crossfadeWithThumb = true; @@ -3123,6 +3102,7 @@ public BackgroundThreadDrawHolder setDrawInBackgroundThread(BackgroundThreadDraw holder.imageShader = imageShader; holder.thumbDrawable = currentThumbDrawable; holder.thumbShader = thumbShader; + holder.staticThumbShader = staticThumbShader; holder.staticThumbDrawable = staticThumbDrawable; holder.crossfadeImage = crossfadeImage; holder.colorFilter = colorFilter; @@ -3145,6 +3125,7 @@ public static class BackgroundThreadDrawHolder { public float overrideAlpha; public long time; public int threadIndex; + public BitmapShader staticThumbShader; private AnimatedFileDrawable animation; private RLottieDrawable lottieDrawable; private int[] roundRadius = new int[4]; @@ -3179,6 +3160,7 @@ public void release() { imageShader = null; thumbDrawable = null; thumbShader = null; + staticThumbShader = null; staticThumbDrawable = null; crossfadeImage = null; colorFilter = null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 5e0d1029dd..5b28b13310 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -2090,9 +2090,9 @@ private long calcFeaturedStickersHash(boolean emoji, ArrayList> 21; - hash ^= id << 35; - hash ^= id >> 4; + hash ^= hash >> 21; + hash ^= hash << 35; + hash ^= hash >> 4; return hash + id; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageLoaderLogger.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageLoaderLogger.java new file mode 100644 index 0000000000..6e7421ae57 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageLoaderLogger.java @@ -0,0 +1,54 @@ +package org.telegram.messenger; + +public class MessageLoaderLogger { + + final long dialogId; + final int count; + final int loadIndex; + final long startTime; + + long moveToStorageQueueTime; + long getFromDatabaseTime; + long moveToStageQueueTime; + long stageQueueProccessing; + + boolean reload; + + public MessageLoaderLogger(long dialogId, int loadIndex, int count) { + this.dialogId = dialogId; + this.count = count; + this.loadIndex = loadIndex; + startTime = System.currentTimeMillis(); + } + + public void logStorageQueuePost() { + moveToStorageQueueTime = System.currentTimeMillis() - startTime; + } + + public void logStorageProccessing() { + getFromDatabaseTime = System.currentTimeMillis() - startTime; + } + + public void logStageQueuePost() { + moveToStageQueueTime = System.currentTimeMillis() - startTime; + } + + public void reload() { + reload = true; + } + + public void logStageQueueProcessing() { + stageQueueProccessing = System.currentTimeMillis() - startTime; + } + + public void finish() { + long totalTime = System.currentTimeMillis() - startTime; + FileLog.d("MessageLoaderLogger dialogId=" + dialogId + " index=" + loadIndex + " count=" + count + " " + + " moveToStorageQueueTime=" + moveToStorageQueueTime + + " getFromDatabaseTime=" + getFromDatabaseTime + + " moveToStageQueueTime=" + moveToStageQueueTime + + " stageQueueProccessing=" + stageQueueProccessing + + " wasReload=" + reload + " totalTime=" + totalTime + ); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 2f9a44f170..120700542c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -1354,7 +1354,7 @@ private void createPathThumb() { } public void createStrippedThumb() { - if (photoThumbs == null || !canCreateStripedThubms() && !hasExtendedMediaPreview()) { + if (photoThumbs == null || !canCreateStripedThubms() && !hasExtendedMediaPreview() || strippedThumb != null) { return; } try { @@ -4835,7 +4835,15 @@ public void generateCaption() { } String text = messageOwner.message; ArrayList entities = messageOwner.entities; - if (hasExtendedMedia()) { + if (type == TYPE_STORY) { + if (messageOwner.media != null && messageOwner.media.storyItem != null) { + text = messageOwner.media.storyItem.caption; + entities = messageOwner.media.storyItem.entities; + } else { + text = ""; + entities = new ArrayList<>(); + } + } else if (hasExtendedMedia()) { text = messageOwner.message = messageOwner.media.description; } if (captionTranslated = translated) { @@ -4844,7 +4852,7 @@ public void generateCaption() { } if (!isMediaEmpty() && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) && !TextUtils.isEmpty(text)) { caption = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); - caption = replaceAnimatedEmoji(caption, Theme.chat_msgTextPaint.getFontMetricsInt()); + caption = replaceAnimatedEmoji(caption, entities, Theme.chat_msgTextPaint.getFontMetricsInt(), false); boolean hasEntities; if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 59c7545261..e93769d90c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -7964,21 +7964,24 @@ public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, in } public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, int mode, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean isTopic) { - loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true, true, isTopic); + loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true, true, isTopic, null); } - private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int minDate, int classGuid, int load_type, int last_message_id, int mode, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean loadDialog, boolean processMessages, boolean isTopic) { + private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int minDate, int classGuid, int load_type, int last_message_id, int mode, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean loadDialog, boolean processMessages, boolean isTopic, MessageLoaderLogger loaderLogger) { if (BuildVars.LOGS_ENABLED) { FileLog.d("load messages in chat " + dialogId + " topic_id " + threadMessageId + " count " + count + " max_id " + max_id + " cache " + fromCache + " mindate = " + minDate + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " mode " + mode + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer + " isTopic " + isTopic); } + if (BuildVars.LOGS_ENABLED && loaderLogger == null && mode == 0) { + loaderLogger = new MessageLoaderLogger(dialogId, loadIndex, count); + } if ((threadMessageId == 0 || isTopic) && mode != 2 && (fromCache || DialogObject.isEncryptedDialog(dialogId))) { - getMessagesStorage().getMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, minDate, classGuid, load_type, mode == 1, threadMessageId, loadIndex, processMessages, isTopic); + getMessagesStorage().getMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, minDate, classGuid, load_type, mode == 1, threadMessageId, loadIndex, processMessages, isTopic, loaderLogger); } else { if (threadMessageId != 0) { if (loadDialog && isTopic && load_type == 2 && last_message_id == 0) { TLRPC.TL_forumTopic topic = topicsController.findTopic(-dialogId, threadMessageId); if (topic != null) { - loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, topic.top_message, 0, threadMessageId, loadIndex, first_unread, topic.unread_count, last_date, queryFromServer, topic.unread_mentions_count, false, processMessages, isTopic); + loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, topic.top_message, 0, threadMessageId, loadIndex, first_unread, topic.unread_count, last_date, queryFromServer, topic.unread_mentions_count, false, processMessages, isTopic, loaderLogger); return; } } @@ -8036,7 +8039,7 @@ private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loa } } } - processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, fnid, last_message_id, unread_count, last_date, load_type, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic); + processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, fnid, last_message_id, unread_count, last_date, load_type, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic, null); } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); } @@ -8064,7 +8067,7 @@ private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loa } } } - processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, false, mode, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic); + processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, false, mode, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic, null); } }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); @@ -8091,7 +8094,7 @@ private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loa getMessagesStorage().putDialogs(dialogs, 2); } - loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, 0, threadMessageId, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false, processMessages, isTopic); + loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, 0, threadMessageId, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false, processMessages, isTopic, null); } } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); @@ -8139,7 +8142,7 @@ private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loa } } } - processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic); + processLoadedMessages(res, res.messages.size(), dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount, processMessages, isTopic, null); } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); } @@ -8198,7 +8201,7 @@ public void reloadWebPages(final long dialogId, HashMap 60 * 1000); } else { reload = resCount == 0 && (!isInitialLoading || (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 60 * 1000 || (isCache && isTopic)); - if (isCache && dialogId < 0) { - TLRPC.Chat chat = getChat(-dialogId); - if (chat == null) { - chat = chatsDict.get(-dialogId); - } - if (chat != null && mode == 0 && ChatObject.isNotInChat(chat) && (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 24 * 60 * 60 * 1000) { - messagesRes.messages.clear(); - reload = true; - } - } +// if (isCache && dialogId < 0) { +// TLRPC.Chat chat = getChat(-dialogId); +// if (chat == null) { +// chat = chatsDict.get(-dialogId); +// } +// if (chat != null && mode == 0 && ChatObject.isNotInChat(chat) && (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 24 * 60 * 60 * 1000) { +// messagesRes.messages.clear(); +// reload = true; +// } +// } } if (!DialogObject.isEncryptedDialog(dialogId) && isCache && reload) { int hash; @@ -8274,7 +8277,10 @@ public void processLoadedMessages(TLRPC.messages_Messages messagesRes, int resCo lastServerQueryTime.put(dialogId, SystemClock.elapsedRealtime()); hash = 0; } - AndroidUtilities.runOnUIThread(() -> loadMessagesInternal(dialogId, mergeDialogId, false, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true, needProcess, isTopic)); + if (loaderLogger != null) { + loaderLogger.reload(); + } + AndroidUtilities.runOnUIThread(() -> loadMessagesInternal(dialogId, mergeDialogId, false, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true, needProcess, isTopic, loaderLogger)); if (messagesRes.messages.isEmpty()) { return; } @@ -8367,10 +8373,16 @@ public void processLoadedMessages(TLRPC.messages_Messages messagesRes, int resCo if (BuildVars.LOGS_ENABLED) { FileLog.d("process time=" + (SystemClock.elapsedRealtime() - startProcessTime) + " count=" + objects.size() + " for dialog " + dialogId); } + if (loaderLogger != null) { + loaderLogger.logStageQueueProcessing(); + } AndroidUtilities.runOnUIThread(() -> { putUsers(messagesRes.users, isCache); putChats(messagesRes.chats, isCache); + if (loaderLogger != null) { + loaderLogger.finish(); + } if (messagesRes.animatedEmoji != null && needProcess) { AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).processDocuments(messagesRes.animatedEmoji); } @@ -12183,6 +12195,9 @@ protected void loadUnknownChannel(final TLRPC.Chat channel, long taskId) { } public void startShortPoll(TLRPC.Chat chat, int guid, boolean stop) { + startShortPoll(chat, guid, stop, null); + } + public void startShortPoll(TLRPC.Chat chat, int guid, boolean stop, Consumer needPollConsumer) { if (chat == null) { return; } @@ -12212,9 +12227,17 @@ public void startShortPoll(TLRPC.Chat chat, int guid, boolean stop) { if (!guids.contains(guid)) { guids.add(guid); } + boolean needGetDifference = false; if (shortPollChannels.indexOfKey(chat.id) < 0) { + needGetDifference = true; getChannelDifference(chat.id, 3, 0, null); } + boolean finalNeedGetDifference = needGetDifference; + if (needPollConsumer != null) { + AndroidUtilities.runOnUIThread(() -> { + needPollConsumer.accept(finalNeedGetDifference); + }); + } if (chat.megagroup) { if (onlineGuids == null) { onlineGuids = new ArrayList<>(); @@ -12259,6 +12282,9 @@ protected void getChannelDifference(long channelId, int newDialogType, long task if (newDialogType == 1) { channelPts = channelsPts.get(channelId); if (channelPts != 0) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); return; } channelPts = 1; @@ -12271,10 +12297,16 @@ protected void getChannelDifference(long channelId, int newDialogType, long task channelsPts.put(channelId, channelPts); } if (channelPts == 0 && (newDialogType == 2 || newDialogType == 3)) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); return; } } if (channelPts == 0) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); return; } } @@ -12293,6 +12325,9 @@ protected void getChannelDifference(long channelId, int newDialogType, long task if (taskId != 0) { getMessagesStorage().removePendingTask(taskId); } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); return; } long newTaskId; @@ -12382,6 +12417,7 @@ protected void getChannelDifference(long channelId, int newDialogType, long task } Utilities.stageQueue.postRunnable(() -> { + boolean notifyAbountDifference = true; if (res instanceof TLRPC.TL_updates_channelDifference || res instanceof TLRPC.TL_updates_channelDifferenceEmpty) { if (!res.new_messages.isEmpty()) { LongSparseArray> messages = new LongSparseArray<>(); @@ -12464,7 +12500,10 @@ protected void getChannelDifference(long channelId, int newDialogType, long task message.dialog_id = -channelId; message.unread = !(message.action instanceof TLRPC.TL_messageActionChannelCreate || channelFinal != null && channelFinal.left || (message.out ? outboxValue : inboxValue) >= message.id); } - getMessagesStorage().overwriteChannel(channelId, (TLRPC.TL_updates_channelDifferenceTooLong) res, newDialogType); + getMessagesStorage().overwriteChannel(channelId, (TLRPC.TL_updates_channelDifferenceTooLong) res, newDialogType, () -> AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + })); + notifyAbountDifference = false; } gettingDifferenceChannels.delete(channelId); channelsPts.put(channelId, res.pts); @@ -12483,10 +12522,18 @@ protected void getChannelDifference(long channelId, int newDialogType, long task if (newTaskId != 0) { getMessagesStorage().removePendingTask(newTaskId); } + if (notifyAbountDifference) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); + } }); }); } else if (error != null) { - AndroidUtilities.runOnUIThread(() -> checkChannelError(error.text, channelId)); + AndroidUtilities.runOnUIThread(() -> { + checkChannelError(error.text, channelId); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); gettingDifferenceChannels.delete(channelId); if (newTaskId != 0) { getMessagesStorage().removePendingTask(newTaskId); @@ -17672,9 +17719,9 @@ public void didReceivedNotification(int id, int account, Object... args) { int lastMessageId = (int) args[4]; if ((size < count / 2 && !isEnd) && isCache) { if (finalMessageId != 0) { - loadMessagesInternal(dialogId, 0, false, count, finalMessageId, 0, false, 0, classGuid, 3, lastMessageId, 0, 0, -1, 0, 0, 0, false, 0, true, false, false); + loadMessagesInternal(dialogId, 0, false, count, finalMessageId, 0, false, 0, classGuid, 3, lastMessageId, 0, 0, -1, 0, 0, 0, false, 0, true, false, false, null); } else { - loadMessagesInternal(dialogId, 0, false, count, finalMessageId, 0, false, 0, classGuid, 2, lastMessageId, 0, 0, -1, 0, 0, 0, false, 0, true, false, false); + loadMessagesInternal(dialogId, 0, false, count, finalMessageId, 0, false, 0, classGuid, 2, lastMessageId, 0, 0, -1, 0, 0, 0, false, 0, true, false, false, null); } } else { getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoadWithoutProcess); @@ -17698,9 +17745,9 @@ public void didReceivedNotification(int id, int account, Object... args) { getNotificationCenter().addObserver(delegate, NotificationCenter.loadingMessagesFailed); if (messageId != 0) { - loadMessagesInternal(dialogId, 0, true, count, finalMessageId, 0, true, 0, classGuid, 3, 0, 0, 0, -1, 0, 0, 0, false, 0, true, false, false); + loadMessagesInternal(dialogId, 0, true, count, finalMessageId, 0, true, 0, classGuid, 3, 0, 0, 0, -1, 0, 0, 0, false, 0, true, false, false, null); } else { - loadMessagesInternal(dialogId, 0, true, count, finalMessageId, 0, true, 0, classGuid, 2, 0, 0, 0, -1, 0, 0, 0, false, 0, true, false, false); + loadMessagesInternal(dialogId, 0, true, count, finalMessageId, 0, true, 0, classGuid, 2, 0, 0, 0, -1, 0, 0, 0, false, 0, true, false, false, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 10a3cbf268..f15a4aa04a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -7729,7 +7729,7 @@ public void getMessagesCount(long dialog_id, IntCallback callback) { }); } - public Runnable getMessagesInternal(long dialogId, long mergeDialogId, int count, int max_id, int offset_date, int minDate, int classGuid, int load_type, boolean scheduled, int threadMessageId, int loadIndex, boolean processMessages, boolean isTopic) { + public Runnable getMessagesInternal(long dialogId, long mergeDialogId, int count, int max_id, int offset_date, int minDate, int classGuid, int load_type, boolean scheduled, int threadMessageId, int loadIndex, boolean processMessages, boolean isTopic, MessageLoaderLogger loaderLogger) { TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages(); long currentUserId = getUserConfig().clientUserId; int count_unread = 0; @@ -8623,7 +8623,7 @@ public Runnable getMessagesInternal(long dialogId, long mergeDialogId, int count }; } else {*/ int finalMessagesCount = scheduled ? res.messages.size() : messagesCount; - return () -> getMessagesController().processLoadedMessages(res, finalMessagesCount, dialogId, mergeDialogId, countQueryFinal, maxIdOverrideFinal, offset_date, true, classGuid, minUnreadIdFinal, lastMessageIdFinal, countUnreadFinal, maxUnreadDateFinal, load_type, isEndFinal, scheduled ? 1 : 0, threadMessageId, loadIndex, queryFromServerFinal, mentionsUnreadFinal, processMessages, isTopic); + return () -> getMessagesController().processLoadedMessages(res, finalMessagesCount, dialogId, mergeDialogId, countQueryFinal, maxIdOverrideFinal, offset_date, true, classGuid, minUnreadIdFinal, lastMessageIdFinal, countUnreadFinal, maxUnreadDateFinal, load_type, isEndFinal, scheduled ? 1 : 0, threadMessageId, loadIndex, queryFromServerFinal, mentionsUnreadFinal, processMessages, isTopic, loaderLogger); //} } @@ -8654,10 +8654,19 @@ private void getAnimatedEmoji(String join, ArrayList documents) } } - public void getMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, int minDate, int classGuid, int load_type, boolean scheduled, int replyMessageId, int loadIndex, boolean processMessages, boolean isTopic) { + public void getMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, int minDate, int classGuid, int load_type, boolean scheduled, int replyMessageId, int loadIndex, boolean processMessages, boolean isTopic, MessageLoaderLogger loaderLogger) { storageQueue.postRunnable(() -> { - Runnable processMessagesRunnable = getMessagesInternal(dialogId, mergeDialogId, count, max_id, offset_date, minDate, classGuid, load_type, scheduled, replyMessageId, loadIndex, processMessages, isTopic); + if (loaderLogger != null) { + loaderLogger.logStorageQueuePost(); + } + Runnable processMessagesRunnable = getMessagesInternal(dialogId, mergeDialogId, count, max_id, offset_date, minDate, classGuid, load_type, scheduled, replyMessageId, loadIndex, processMessages, isTopic, loaderLogger); + if (loaderLogger != null) { + loaderLogger.logStorageProccessing(); + } Utilities.stageQueue.postRunnable(() -> { + if (loaderLogger != null) { + loaderLogger.logStageQueuePost(); + } processMessagesRunnable.run(); }); }); @@ -9908,7 +9917,7 @@ public void putWebPages(LongSparseArray webPages) { }); } - public void overwriteChannel(long channelId, TLRPC.TL_updates_channelDifferenceTooLong difference, int newDialogType) { + public void overwriteChannel(long channelId, TLRPC.TL_updates_channelDifferenceTooLong difference, int newDialogType, Runnable onDone) { storageQueue.postRunnable(() -> { SQLiteCursor cursor = null; try { @@ -9978,6 +9987,9 @@ public void overwriteChannel(long channelId, TLRPC.TL_updates_channelDifferenceT cursor.dispose(); } } + if (onDone != null) { + onDone.run(); + } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 76cf3dfc45..0211c54e9c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -288,6 +288,8 @@ public class NotificationCenter { public static final int uploadStoryProgress = totalEvents++; public static final int uploadStoryEnd = totalEvents++; public static final int customTypefacesLoaded = totalEvents++; + public static final int stealthModeChanged = totalEvents++; + public static final int onReceivedChannelDifference = totalEvents++; public static boolean alreadyLogged; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index f9714e3ae5..1c27888a31 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -4325,7 +4325,7 @@ private void showExtraNotifications(NotificationCompat.Builder notificationBuild notificationBuilder.setChannelId(validateChannelId(lastDialogId, lastTopicId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType)); } Notification mainNotification = notificationBuilder.build(); - if (Build.VERSION.SDK_INT < 18) { + if (Build.VERSION.SDK_INT <= 19) { notificationManager.notify(notificationId, mainNotification); if (BuildVars.LOGS_ENABLED) { FileLog.d("show summary notification by SDK check"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SaveToGallerySettingsHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SaveToGallerySettingsHelper.java index 80c7cfe973..aa38edde14 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SaveToGallerySettingsHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SaveToGallerySettingsHelper.java @@ -206,7 +206,7 @@ public CharSequence createDescription(int currentAccount) { } builder.append(LocaleController.getString("SaveToGalleryVideos", R.string.SaveToGalleryVideos)); if (limitVideo > 0 && limitVideo < 4L * 1000 * 1024 * 1024) { - builder.append(" (").append(AndroidUtilities.formatFileSize(limitVideo, true)).append(")"); + builder.append(" (").append(AndroidUtilities.formatFileSize(limitVideo, true, false)).append(")"); } } } else { @@ -244,7 +244,7 @@ public CharSequence createDescription(int currentAccount) { } if (limitVideo > 0 && limitVideo < 4L * 1000 * 1024 * 1024) { - builder.append(LocaleController.formatString("SaveToGalleryVideosUpTo", R.string.SaveToGalleryVideosUpTo, AndroidUtilities.formatFileSize(limitVideo, true))); + builder.append(LocaleController.formatString("SaveToGalleryVideosUpTo", R.string.SaveToGalleryVideosUpTo, AndroidUtilities.formatFileSize(limitVideo, true, false))); } else { builder.append(LocaleController.formatString("SaveToGalleryVideos", R.string.SaveToGalleryVideos)); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java index 1425baaf91..9b9bf24973 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java @@ -43,6 +43,8 @@ import androidx.core.graphics.ColorUtils; +import com.google.android.exoplayer2.util.Log; + import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.DrawingInBackgroundThreadDrawable; import org.xml.sax.Attributes; @@ -109,19 +111,19 @@ public static class SvgDrawable extends Drawable { private Paint backgroundPaint; protected int width; protected int height; - private static int[] parentPosition = new int[2]; + private static final int[] parentPosition = new int[2]; - private Bitmap[] backgroundBitmap = new Bitmap[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; - private Canvas[] backgroundCanvas = new Canvas[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; - private LinearGradient[] placeholderGradient = new LinearGradient[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; - private Matrix[] placeholderMatrix = new Matrix[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; + private final Bitmap[] backgroundBitmap = new Bitmap[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; + private final Canvas[] backgroundCanvas = new Canvas[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; + private final LinearGradient[] placeholderGradient = new LinearGradient[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; + private final Matrix[] placeholderMatrix = new Matrix[1 + DrawingInBackgroundThreadDrawable.THREAD_COUNT]; private static float totalTranslation; private static float gradientWidth; private static long lastUpdateTime; private static Runnable shiftRunnable; private static WeakReference shiftDrawable; private ImageReceiver parentImageReceiver; - private int[] currentColor = new int[2]; + private final int[] currentColor = new int[2]; private int currentColorKey; private Integer overrideColor; private Theme.ResourcesProvider currentResourcesProvider; @@ -441,6 +443,7 @@ public static Bitmap getBitmap(int res, int width, int height, int color, float SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); SVGHandler handler = new SVGHandler(width, height, color, false, scale); + ///handler.alphaOnly = true; xr.setContentHandler(handler); xr.parse(new InputSource(stream)); return handler.getBitmap(); @@ -456,6 +459,9 @@ public static Bitmap getBitmap(File file, int width, int height, boolean white) SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); SVGHandler handler = new SVGHandler(width, height, white ? 0xffffffff : null, false, 1f); + if (!white) { + handler.alphaOnly = true; + } xr.setContentHandler(handler); xr.parse(new InputSource(stream)); return handler.getBitmap(); @@ -1116,6 +1122,7 @@ private static class SVGHandler extends DefaultHandler { boolean pushed = false; private HashMap globalStyles = new HashMap<>(); + private boolean alphaOnly; private SVGHandler(int dw, int dh, Integer color, boolean asDrawable, float scale) { globalScale = scale; @@ -1275,7 +1282,7 @@ public void startElement(String namespaceURI, String localName, String qName, At height *= scale; } if (drawable == null) { - bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap = Bitmap.createBitmap(width, height, alphaOnly ? Bitmap.Config.ALPHA_8 : Bitmap.Config.ARGB_8888); bitmap.eraseColor(0); canvas = new Canvas(bitmap); if (scale != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/RoundVideoShadow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/RoundVideoShadow.java new file mode 100644 index 0000000000..f4eb6887be --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/RoundVideoShadow.java @@ -0,0 +1,57 @@ +package org.telegram.ui.ActionBar; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; + +public class RoundVideoShadow extends Drawable { + + Paint eraserPaint; + Paint paint; + + public RoundVideoShadow() { +// eraserPaint = new Paint(Paint.ANTI_ALIAS_FLAG); +// eraserPaint.setColor(0); +// eraserPaint.setStyle(Paint.Style.FILL); +// eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setShadowLayer(AndroidUtilities.dp(4), 0, 0, 0x5f000000); + } + + @Override + public void draw(@NonNull Canvas canvas) { + float cx = getBounds().centerX(); + float cy = getBounds().centerY(); +// for (int a = 0; a < 2; a++) { +// canvas.drawCircle(cx, cy, AndroidUtilities.roundMessageSize / 2f - AndroidUtilities.dp(1), a == 0 ? paint : eraserPaint); +// } + float r = (getBounds().width() - AndroidUtilities.dp(8)) / 2f; + canvas.drawCircle(cx, cy - AndroidUtilities.dp(1), r, paint); + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + // eraserPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return 0; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 7be374934e..3ee0b432ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -3197,7 +3197,6 @@ public void run() { public static Drawable chat_inlineResultFile; public static Drawable chat_inlineResultAudio; public static Drawable chat_inlineResultLocation; - public static Drawable chat_redLocationIcon; public static Drawable chat_msgOutLocationDrawable; public static Drawable chat_contextResult_shadowUnderSwitchDrawable; public static Drawable chat_shareIconDrawable; @@ -3226,7 +3225,6 @@ public void run() { public static Drawable chat_msgCallDownRedDrawable; public static Drawable chat_msgCallDownGreenDrawable; - public static Drawable chat_msgAvatarLiveLocationDrawable; public static Drawable chat_attachEmptyDrawable; public static RLottieDrawable[] chat_attachButtonDrawables = new RLottieDrawable[6]; public static Drawable[] chat_locationDrawable = new Drawable[2]; @@ -7670,11 +7668,17 @@ protected int getCurrentColor(int key) { options.inSampleSize *= 2; } while (options.inSampleSize < scale); } + options.inPreferredConfig = Bitmap.Config.ALPHA_8; options.inJustDecodeBounds = false; Bitmap wallpaper = BitmapFactory.decodeFile(wallpaperPath, options); if (wallpaper != null) { if (color2 != 0 && accent != null) { MotionBackgroundDrawable wallpaperDrawable = new MotionBackgroundDrawable(backColor, color1, color2, color3, true); + if (bitmap != null && bitmap.getConfig() != Bitmap.Config.ALPHA_8) { + Bitmap toRecycle = bitmap; + bitmap = bitmap.copy(Bitmap.Config.ALPHA_8, false); + toRecycle.recycle(); + } wallpaperDrawable.setPatternBitmap((int) (accent.patternIntensity * 100), wallpaper); wallpaperDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); wallpaperDrawable.draw(canvas); @@ -8466,12 +8470,10 @@ public static void createChatResources(Context context, boolean fontsOnly) { calllog_msgCallUpGreenDrawable = resources.getDrawable(R.drawable.ic_call_made_green_18dp).mutate(); calllog_msgCallDownRedDrawable = resources.getDrawable(R.drawable.ic_call_received_green_18dp).mutate(); calllog_msgCallDownGreenDrawable = resources.getDrawable(R.drawable.ic_call_received_green_18dp).mutate(); - chat_msgAvatarLiveLocationDrawable = resources.getDrawable(R.drawable.livepin).mutate(); chat_inlineResultFile = resources.getDrawable(R.drawable.bot_file); chat_inlineResultAudio = resources.getDrawable(R.drawable.bot_music); chat_inlineResultLocation = resources.getDrawable(R.drawable.bot_location); - chat_redLocationIcon = resources.getDrawable(R.drawable.map_pin).mutate(); chat_botLinkDrawable = resources.getDrawable(R.drawable.bot_link); chat_botInlineDrawable = resources.getDrawable(R.drawable.bot_lines); @@ -8545,29 +8547,7 @@ public static void createChatResources(Context context, boolean fontsOnly) { chat_composeShadowDrawable = context.getResources().getDrawable(R.drawable.compose_panel_shadow).mutate(); chat_composeShadowRoundDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); - try { - int bitmapSize = AndroidUtilities.roundMessageSize + AndroidUtilities.dp(6); - Bitmap bitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - Paint eraserPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - eraserPaint.setColor(0); - eraserPaint.setStyle(Paint.Style.FILL); - eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setShadowLayer(AndroidUtilities.dp(4), 0, 0, 0x5f000000); - for (int a = 0; a < 2; a++) { - canvas.drawCircle(bitmapSize / 2, bitmapSize / 2, AndroidUtilities.roundMessageSize / 2 - AndroidUtilities.dp(1), a == 0 ? paint : eraserPaint); - } - try { - canvas.setBitmap(null); - } catch (Exception ignore) { - - } - chat_roundVideoShadow = new BitmapDrawable(bitmap); - } catch (Throwable ignore) { - - } + chat_roundVideoShadow = new RoundVideoShadow(); defaultChatDrawables.clear(); defaultChatDrawableColorKeys.clear(); @@ -9590,7 +9570,15 @@ public static BackgroundDrawableSettings createBackgroundDrawable( try { if (backgroundColor != 0 && gradientToColor1 != 0 && gradientToColor2 != 0) { MotionBackgroundDrawable motionBackgroundDrawable = new MotionBackgroundDrawable(backgroundColor, gradientToColor1, gradientToColor2, gradientToColor3, false); - motionBackgroundDrawable.setPatternBitmap(intensity, BitmapFactory.decodeFile(wallpaperFile.getAbsolutePath())); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = Bitmap.Config.ALPHA_8; + Bitmap patternBitmap = BitmapFactory.decodeFile(wallpaperFile.getAbsolutePath(), options); + if (patternBitmap != null && patternBitmap.getConfig() != Bitmap.Config.ALPHA_8) { + Bitmap toRecycle = patternBitmap; + patternBitmap = patternBitmap.copy(Bitmap.Config.ALPHA_8, false); + toRecycle.recycle(); + } + motionBackgroundDrawable.setPatternBitmap(intensity, patternBitmap); motionBackgroundDrawable.setPatternColorFilter(motionBackgroundDrawable.getPatternColor()); settings.wallpaper = motionBackgroundDrawable; } else { @@ -9932,6 +9920,7 @@ public void onSizeReady(int width, int height) { photoH /= 2; } } + opts.inPreferredConfig = Bitmap.Config.ALPHA_8; opts.inJustDecodeBounds = false; opts.inSampleSize = scaleFactor; Bitmap bitmap = BitmapFactory.decodeStream(stream, null, opts); @@ -9943,6 +9932,11 @@ public void onSizeReady(int width, int height) { } else { intensity = 100; } + if (bitmap != null && bitmap.getConfig() != Bitmap.Config.ALPHA_8) { + Bitmap toRecycle = bitmap; + bitmap = bitmap.copy(Bitmap.Config.ALPHA_8, false); + toRecycle.recycle(); + } motionBackgroundDrawable.setPatternBitmap(intensity, bitmap); motionBackgroundDrawable.setPatternColorFilter(motionBackgroundDrawable.getPatternColor()); return motionBackgroundDrawable; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index fe194b4db6..e6d9222140 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -92,6 +92,7 @@ import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; +import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManagerFixed; @@ -309,6 +310,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @SuppressLint("StaticFieldLeak") private static volatile ArticleViewer Instance = null; + private Drawable chat_redLocationIcon; public static ArticleViewer getInstance() { ArticleViewer localInstance = Instance; @@ -757,7 +759,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { MotionEvent textSelectionEv = MotionEvent.obtain(ev); textSelectionEv.offsetLocation(-containerView.getX(), -containerView.getY()); - if (textSelectionHelper.isSelectionMode() && textSelectionHelper.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { + if (textSelectionHelper.isInSelectionMode() && textSelectionHelper.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { return true; } @@ -765,7 +767,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { ev.setAction(MotionEvent.ACTION_CANCEL); } - if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isSelectionMode() && (ev.getY() < containerView.getTop() || ev.getY() > containerView.getBottom())) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isInSelectionMode() && (ev.getY() < containerView.getTop() || ev.getY() > containerView.getBottom())) { if (textSelectionHelper.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { return super.dispatchTouchEvent(ev); } else { @@ -906,7 +908,7 @@ private void prepareForMoving(MotionEvent ev) { } public boolean handleTouchEvent(MotionEvent event) { - if (pageSwitchAnimation == null && !closeAnimationInProgress && fullscreenVideoContainer.getVisibility() != VISIBLE && !textSelectionHelper.isSelectionMode()) { + if (pageSwitchAnimation == null && !closeAnimationInProgress && fullscreenVideoContainer.getVisibility() != VISIBLE && !textSelectionHelper.isInSelectionMode()) { if (event != null && event.getAction() == MotionEvent.ACTION_DOWN && !startedTracking && !maybeStartTracking) { startedTrackingPointerId = event.getPointerId(0); maybeStartTracking = true; @@ -1035,7 +1037,7 @@ public void onAnimationEnd(Animator animator) { tracker.recycle(); tracker = null; } - if (textSelectionHelper != null && !textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && !textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); } } @@ -1134,7 +1136,7 @@ public void run() { } else { textSelectionHelper.trySelect(pressedLinkOwnerView); } - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { windowView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } } else if (pressedLinkOwnerLayout != null && pressedLinkOwnerView != null) { @@ -1733,7 +1735,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { TextSelectionHelper.TextSelectionOverlay selectionOverlay = textSelectionHelperBottomSheet.getOverlayView(getContext()); MotionEvent textSelectionEv = MotionEvent.obtain(ev); textSelectionEv.offsetLocation(-linearLayout.getX(), -linearLayout.getY()); - if (textSelectionHelperBottomSheet.isSelectionMode() && textSelectionHelperBottomSheet.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { + if (textSelectionHelperBottomSheet.isInSelectionMode() && textSelectionHelperBottomSheet.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { return true; } @@ -1741,7 +1743,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { ev.setAction(MotionEvent.ACTION_CANCEL); } - if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelperBottomSheet.isSelectionMode() && (ev.getY() < linearLayout.getTop() || ev.getY() > linearLayout.getBottom())) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelperBottomSheet.isInSelectionMode() && (ev.getY() < linearLayout.getTop() || ev.getY() > linearLayout.getBottom())) { if (textSelectionHelperBottomSheet.getOverlayView(getContext()).onTouchEvent(textSelectionEv)) { return super.dispatchTouchEvent(ev); } else { @@ -1762,7 +1764,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { builder.setDelegate(new BottomSheet.BottomSheetDelegate() { @Override public boolean canDismiss() { - if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isSelectionMode()){ + if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isInSelectionMode()){ textSelectionHelperBottomSheet.clear(); return false; } @@ -1773,7 +1775,7 @@ public boolean canDismiss() { frameLayout.addView(linearLayout, LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT); frameLayout.addView(overlayView, LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT); builder.setCustomView(frameLayout); - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); } showDialog(linkSheet = builder.create()); @@ -3186,7 +3188,7 @@ public void setTranslationX(float translationX) { }); listView[i].setOnItemClickListener((view, position, x, y) -> { if (textSelectionHelper != null) { - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); return; } @@ -4580,7 +4582,7 @@ public void close(boolean byBackPress, boolean force) { return; } } - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); return; } @@ -7541,7 +7543,7 @@ protected void onScrollChanged(int l, int t, int oldl, int oldt) { pressedLinkOwnerView = null; } updateChildTextPositions(); - if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { textSelectionHelper.invalidate(); } } @@ -10394,13 +10396,16 @@ protected void onDraw(Canvas canvas) { imageView.draw(canvas); if (currentMapProvider == 2 && imageView.hasNotThumb()) { - int w = (int) (Theme.chat_redLocationIcon.getIntrinsicWidth() * 0.8f); - int h = (int) (Theme.chat_redLocationIcon.getIntrinsicHeight() * 0.8f); + if (chat_redLocationIcon == null) { + chat_redLocationIcon = ContextCompat.getDrawable(getContext(), R.drawable.map_pin).mutate(); + } + int w = (int) (chat_redLocationIcon.getIntrinsicWidth() * 0.8f); + int h = (int) (chat_redLocationIcon.getIntrinsicHeight() * 0.8f); int x = (int) (imageView.getImageX() + (imageView.getImageWidth() - w) / 2); int y = (int) (imageView.getImageY() + (imageView.getImageHeight() / 2 - h)); - Theme.chat_redLocationIcon.setAlpha((int) (255 * imageView.getCurrentAlpha())); - Theme.chat_redLocationIcon.setBounds(x, y, x + w, y + h); - Theme.chat_redLocationIcon.draw(canvas); + chat_redLocationIcon.setAlpha((int) (255 * imageView.getCurrentAlpha())); + chat_redLocationIcon.setBounds(x, y, x + w, y + h); + chat_redLocationIcon.draw(canvas); } int count = 0; if (captionLayout != null) { @@ -11059,7 +11064,7 @@ protected void onDraw(Canvas canvas) { if (Build.VERSION.SDK_INT >= 23) { scrollView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { - if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { textSelectionHelper.invalidate(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 5ece31b4d4..83af78d8e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -149,7 +149,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private LinearLayoutManager layoutManager; AlertDialog progressDialog; - private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true }; + private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true, true }; private long databaseSize = -1; private long cacheSize = -1, cacheEmojiSize = -1, cacheTempSize = -1; private long documentsSize = -1; @@ -374,7 +374,7 @@ public boolean onFragmentCreate() { if (canceled) { return; } - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + storiesSize + stickersCacheSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); File path; @@ -441,13 +441,13 @@ public boolean onFragmentCreate() { private void updateChart() { if (cacheChart != null) { if (!calculating && totalSize > 0) { - CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[9]; + CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[10]; for (int i = 0; i < itemInners.size(); ++i) { ItemInner item = itemInners.get(i); if (item.viewType == VIEW_TYPE_SECTION) { if (item.index < 0) { if (collapsed) { - segments[8] = CacheChart.SegmentSize.of(item.size, selected[8]); + segments[9] = CacheChart.SegmentSize.of(item.size, selected[9]); } } else { segments[item.index] = CacheChart.SegmentSize.of(item.size, selected[item.index]); @@ -716,13 +716,13 @@ private void updateRows(boolean animated) { sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalDocumentCache), 2, documentsSize, Theme.key_statisticChartLine_green)); } if (musicSize > 0) { - sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalMusicCache), 3, musicSize, Theme.key_statisticChartLine_red)); + sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalMusicCache), 3, musicSize, Theme.key_statisticChartLine_purple)); } if (audioSize > 0) { sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalAudioCache), 4, audioSize, Theme.key_statisticChartLine_lightgreen)); } if (storiesSize > 0) { - sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalStoriesCache), 5, storiesSize, Theme.key_statisticChartLine_indigo)); + sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalStoriesCache), 5, storiesSize, Theme.key_statisticChartLine_red)); } if (stickersCacheSize > 0) { sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalStickersCache), 6, stickersCacheSize, Theme.key_statisticChartLine_orange)); @@ -739,13 +739,13 @@ private void updateRows(boolean animated) { hasCache = true; if (tempSizes == null) { - tempSizes = new float[9]; + tempSizes = new float[10]; } for (int i = 0; i < tempSizes.length; ++i) { tempSizes[i] = (float) size(i); } if (percents == null) { - percents = new int[9]; + percents = new int[10]; } AndroidUtilities.roundPercents(tempSizes, percents); @@ -759,7 +759,7 @@ private void updateRows(boolean animated) { sum += sections.get(i).size; sumPercents += percents[sections.get(i).index]; } - percents[8] = sumPercents; + percents[9] = sumPercents; itemInners.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalOther), -1, sum, Theme.key_statisticChartLine_golden)); if (!collapsed) { itemInners.addAll(sections.subList(MAX_NOT_COLLAPSED, sections.size())); @@ -963,7 +963,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre long clearedSize = 0; boolean allItemsClear = true; final int[] clearDirI = new int[] { 0 }; - int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0); + int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0) + (selected[8] ? 1 : 0); long time = System.currentTimeMillis(); Utilities.Callback updateProgress = t -> { onProgress.run(clearDirI[0] / (float) clearDirCount + (1f / clearDirCount) * MathUtils.clamp(t, 0, 1), false); @@ -1001,7 +1001,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre clearedSize += storiesSize; } else if (a == 6) { type = 100; - clearedSize += stickersCacheSize + cacheEmojiSize; + clearedSize += stickersCacheSize; } else if (a == 7) { clearedSize += cacheSize; documentsMusicType = 5; @@ -1088,7 +1088,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre } } final boolean imagesClearedFinal = imagesCleared; - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); Arrays.fill(selected, true); @@ -1176,16 +1176,17 @@ private long size(int type) { case 2: return documentsSize; case 3: return musicSize; case 4: return audioSize; - case 5: return stickersCacheSize; - case 6: return cacheSize; - case 7: return cacheTempSize; + case 5: return storiesSize; + case 6: return stickersCacheSize; + case 7: return cacheSize; + case 8: return cacheTempSize; default: return 0; } } private int sectionsSelected() { int count = 0; - for (int i = 0; i < 8; ++i) { + for (int i = 0; i < 9; ++i) { if (selected[i] && size(i) > 0) { count++; } 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 c33877c6f0..8d2a8be2ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -84,6 +84,7 @@ import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.ChatMessageSharedResources; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; @@ -1287,6 +1288,7 @@ public void run() { private Theme.ResourcesProvider resourcesProvider; private final boolean canDrawBackgroundInParent; + private ChatMessageSharedResources sharedResources; // Public for enter transition public List replySpoilers = new ArrayList<>(); @@ -1298,13 +1300,17 @@ public void run() { public boolean isBlurred; public ChatMessageCell(Context context) { - this(context, false, null); + this(context, false, null, null); } - public ChatMessageCell(Context context, boolean canDrawBackgroundInParent, Theme.ResourcesProvider resourcesProvider) { + public ChatMessageCell(Context context, boolean canDrawBackgroundInParent, ChatMessageSharedResources sharedResources, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.canDrawBackgroundInParent = canDrawBackgroundInParent; + this.sharedResources = sharedResources; + if (this.sharedResources == null) { + this.sharedResources = new ChatMessageSharedResources(context); + } backgroundDrawable = new MessageBackgroundDrawable(this); avatarImage = new ImageReceiver(); @@ -10293,13 +10299,14 @@ protected void onOpen() { } } if (currentMessageObject.type == MessageObject.TYPE_GEO && !(MessageObject.getMedia(currentMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGeoLive) && currentMapProvider == 2 && photoImage.hasNotThumb()) { - int w = (int) (Theme.chat_redLocationIcon.getIntrinsicWidth() * 0.8f); - int h = (int) (Theme.chat_redLocationIcon.getIntrinsicHeight() * 0.8f); + Drawable redLocationIcon = sharedResources.getRedLocationIcon(); + int w = (int) (redLocationIcon.getIntrinsicWidth() * 0.8f); + int h = (int) (redLocationIcon.getIntrinsicHeight() * 0.8f); int x = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - w) / 2); int y = (int) (photoImage.getImageY() + (photoImage.getImageHeight() / 2 - h) - AndroidUtilities.dp(16) * (1f - CubicBezierInterpolator.EASE_OUT_BACK.getInterpolation(photoImage.getCurrentAlpha()))); - Theme.chat_redLocationIcon.setAlpha((int) (255 * Math.min(1, photoImage.getCurrentAlpha() * 5))); - Theme.chat_redLocationIcon.setBounds(x, y, x + w, y + h); - Theme.chat_redLocationIcon.draw(canvas); + redLocationIcon.setAlpha((int) (255 * Math.min(1, photoImage.getCurrentAlpha() * 5))); + redLocationIcon.setBounds(x, y, x + w, y + h); + redLocationIcon.draw(canvas); if (photoImage.getCurrentAlpha() < 1) { invalidate(); } @@ -17192,9 +17199,10 @@ public void drawOverlays(Canvas canvas) { int cx = (int) (photoImage.getImageX() + photoImage.getImageWidth() / 2 - AndroidUtilities.dp(31)); cy = (int) (photoImage.getImageY() + photoImage.getImageHeight() / 2 - AndroidUtilities.dp(38) - AndroidUtilities.dp(16) * (1f - CubicBezierInterpolator.EASE_OUT_BACK.getInterpolation(progress))); - setDrawableBounds(Theme.chat_msgAvatarLiveLocationDrawable, cx, cy); - Theme.chat_msgAvatarLiveLocationDrawable.setAlpha((int) (255 * Math.min(1, progress * 5))); - Theme.chat_msgAvatarLiveLocationDrawable.draw(canvas); + Drawable msgAvatarLiveLocation = sharedResources.getAvatarLiveLocation(); + setDrawableBounds(msgAvatarLiveLocation, cx, cy); + msgAvatarLiveLocation.setAlpha((int) (255 * Math.min(1, progress * 5))); + msgAvatarLiveLocation.draw(canvas); locationImageReceiver.setImageCoords(cx + AndroidUtilities.dp(5.0f), cy + AndroidUtilities.dp(5.0f), AndroidUtilities.dp(52), AndroidUtilities.dp(52)); locationImageReceiver.setAlpha(Math.min(1, progress * 5)); 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 c6c0a8ff6e..eea62e77c9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -104,6 +104,7 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.DialogsActivity; import org.telegram.ui.RightSlidingDialogContainer; +import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.StoryViewer; @@ -185,7 +186,7 @@ public void onLongPress() { } }; - private Path thumbPath = new Path(); + private Path thumbPath; private SpoilerEffect thumbSpoiler = new SpoilerEffect(); public void setMoving(boolean moving) { @@ -708,6 +709,7 @@ protected void onDetachedFromWindow() { AnimatedEmojiSpan.release(this, animatedEmojiStack3); AnimatedEmojiSpan.release(this, animatedEmojiStackName); storyParams.onDetachFromWindow(); + canvasButton = null; } @Override @@ -3765,7 +3767,11 @@ protected void onDraw(Canvas canvas) { ); thumbImage[i].draw(canvas); if (drawSpoiler[i]) { - thumbPath.rewind(); + if (thumbPath == null) { + thumbPath = new Path(); + } else { + thumbPath.rewind(); + } thumbPath.addRoundRect(AndroidUtilities.rectTmp, thumbImage[i].getRoundRadius()[0], thumbImage[i].getRoundRadius()[1], Path.Direction.CW); canvas.save(); @@ -4383,7 +4389,10 @@ public void startOutAnimation() { } else { archivedChatsDrawable.outCy = storyParams.originalAvatarRect.centerY(); archivedChatsDrawable.outCx = storyParams.originalAvatarRect.centerX(); - archivedChatsDrawable.outRadius = avatarImage.getImageWidth() / 2.0f; + archivedChatsDrawable.outRadius = storyParams.originalAvatarRect.width() / 2.0f; + if (MessagesController.getInstance(currentAccount).getStoriesController().hasHiddenStories()) { + archivedChatsDrawable.outRadius -= AndroidUtilities.dpf2(3.5f); + } archivedChatsDrawable.outImageSize = avatarImage.getBitmapWidth(); } archivedChatsDrawable.startOutAnimation(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index bfcd3ff9e1..4a50325a5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -37,6 +37,7 @@ import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AvatarDrawable; @@ -45,14 +46,17 @@ import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.LaunchActivity; import org.telegram.ui.NotificationsSettingsActivity; +import org.telegram.ui.Stories.StoriesListPlaceProvider; +import org.telegram.ui.Stories.StoriesUtilities; import java.util.Locale; public class ProfileSearchCell extends BaseCell implements NotificationCenter.NotificationCenterDelegate { private CharSequence currentName; - private ImageReceiver avatarImage; + public ImageReceiver avatarImage; private AvatarDrawable avatarDrawable; private CharSequence subLabel; private Theme.ResourcesProvider resourcesProvider; @@ -102,6 +106,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No private int statusLeft; private StaticLayout statusLayout; private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable statusDrawable; + public StoriesUtilities.AvatarStoryParams avatarStoryParams = new StoriesUtilities.AvatarStoryParams(false); private RectF rect = new RectF(); @@ -503,8 +508,7 @@ public void buildLayout() { } else { avatarLeft = AndroidUtilities.dp(11) + getPaddingLeft(); } - - avatarImage.setImageCoords(avatarLeft, AndroidUtilities.dp(7), AndroidUtilities.dp(46), AndroidUtilities.dp(46)); + avatarStoryParams.originalAvatarRect.set(avatarLeft, AndroidUtilities.dp(7), avatarLeft + AndroidUtilities.dp(46), AndroidUtilities.dp(7) + AndroidUtilities.dp(46)); double widthpx; float left; @@ -745,7 +749,7 @@ protected void onDraw(Canvas canvas) { actionLayout.draw(canvas); canvas.restore(); } - avatarImage.draw(canvas); + StoriesUtilities.drawAvatarWithStory(dialog_id, canvas, avatarImage, avatarStoryParams); } @Override @@ -790,6 +794,9 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { @Override public boolean onTouchEvent(MotionEvent event) { + if (avatarStoryParams.checkOnTouchEvent(event, this)) { + return true; + } if (actionButton != null && actionButton.checkTouchEvent(event)) { return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java index 284ea264a4..b3559708e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -38,6 +38,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.widget.NestedScrollView; import androidx.recyclerview.widget.LinearLayoutManager; import org.telegram.messenger.AndroidUtilities; @@ -281,6 +282,9 @@ public void run() { } }; + protected Theme.ResourcesProvider resourcesProvider; + public boolean useMovingOffset = true; + private boolean invalidateParent; public TextSelectionHelper() { longpressDelay = ViewConfiguration.getLongPressTimeout(); @@ -288,6 +292,11 @@ public TextSelectionHelper() { selectionPaint.setPathEffect(new CornerPathEffect(cornerRadius = AndroidUtilities.dp(6))); } + public void setInvalidateParent() { + invalidateParent = true; + } + + public interface OnTranslateListener { public void run(CharSequence text, String fromLang, String toLang, Runnable onAlertDismiss); } @@ -381,7 +390,7 @@ private void showMagnifier(int x) { int offset = movingHandleStart ? selectionStart : selectionEnd; fillLayoutForOffset(offset, layoutBlock); - StaticLayout layout = layoutBlock.layout; + Layout layout = layoutBlock.layout; if (layout == null) { return; } @@ -389,17 +398,18 @@ private void showMagnifier(int x) { int line = layout.getLineForOffset(offset); int lineHeight = layout.getLineBottom(line) - layout.getLineTop(line); - int newY = (int) (layout.getLineTop(line) + textY + selectedView.getY()) - lineHeight - AndroidUtilities.dp(8); + int[] coordsInParent = getCoordsInParent(); + int newY = (int) (layout.getLineTop(line) + textY + coordsInParent[1]) - lineHeight - AndroidUtilities.dp(8); newY += layoutBlock.yOffset; int startLine; int endLine; if (selectedView instanceof ArticleViewer.BlockTableCell) { - startLine = (int) selectedView.getX(); - endLine = (int) selectedView.getX() + selectedView.getMeasuredWidth(); + startLine = (int) coordsInParent[0]; + endLine = (int) coordsInParent[0] + selectedView.getMeasuredWidth(); } else { - startLine = (int) (selectedView.getX() + textX + layout.getLineLeft(line)); - endLine = (int) (selectedView.getX() + textX + layout.getLineRight(line)); + startLine = (int) (coordsInParent[0] + textX + layout.getLineLeft(line)); + endLine = (int) (coordsInParent[0] + textX + layout.getLineRight(line)); } if (x < startLine) { x = startLine; @@ -467,7 +477,7 @@ protected void showHandleViews() { handleViewAnimator.start(); } - public boolean isSelectionMode() { + public boolean isInSelectionMode() { return selectionStart >= 0 && selectionEnd >= 0; } @@ -481,7 +491,7 @@ private void showActions() { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!movingHandle && isSelectionMode() && canShowActions()) { + if (!movingHandle && isInSelectionMode() && canShowActions()) { if (!actionsIsShowing) { if (actionMode == null) { FloatingToolbar floatingToolbar = new FloatingToolbar(textSelectionOverlay.getContext(), textSelectionOverlay, STYLE_THEME, getResourcesProvider()); @@ -496,11 +506,11 @@ private void showActions() { } } else { if (!showActionsAsPopupAlways) { - if (actionMode == null && isSelectionMode()) { + if (actionMode == null && isInSelectionMode()) { actionMode = textSelectionOverlay.startActionMode(textSelectActionCallback); } } else { - if (!movingHandle && isSelectionMode() && canShowActions()) { + if (!movingHandle && isInSelectionMode() && canShowActions()) { if (popupLayout == null) { popupRect = new android.graphics.Rect(); popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(textSelectionOverlay.getContext()); @@ -544,7 +554,8 @@ private void showActions() { if (selectedView != null) { int lineHeight = -getLineHeight(); int[] coords = offsetToCord(selectionStart); - y = (int) (coords[1] + textY + selectedView.getY()) + lineHeight / 2 - AndroidUtilities.dp(4); + int[] coordsInParent = getCoordsInParent(); + y = (int) (coords[1] + textY + coordsInParent[1]) + lineHeight / 2 - AndroidUtilities.dp(4); if (y < 0) y = 0; } @@ -580,7 +591,7 @@ private void hideActions() { } actionsIsShowing = false; } - if (!isSelectionMode() && actionMode != null) { + if (!isInSelectionMode() && actionMode != null) { actionMode.finish(); actionMode = null; } @@ -658,7 +669,7 @@ public boolean isTryingSelect() { } public void onParentScrolled() { - if (isSelectionMode() && textSelectionOverlay != null) { + if (isInSelectionMode() && textSelectionOverlay != null) { parentIsScrolling = true; textSelectionOverlay.invalidate(); hideActions(); @@ -695,7 +706,7 @@ public TextSelectionOverlay(Context context) { public boolean checkOnTap(MotionEvent event) { - if (!isSelectionMode() || movingHandle) return false; + if (!isInSelectionMode() || movingHandle) return false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: pressedX = event.getX(); @@ -717,7 +728,7 @@ public boolean checkOnTap(MotionEvent event) { @Override public boolean onTouchEvent(MotionEvent event) { - if (!isSelectionMode()) return false; + if (!isInSelectionMode()) return false; if (event.getPointerCount() > 1) { return movingHandle; } @@ -747,8 +758,13 @@ public boolean onTouchEvent(MotionEvent event) { float textSizeHalf = getLineHeight() / 2; - movingOffsetX = cords[0] + textX + selectedView.getX() - x; - movingOffsetY = cords[1] + textY + selectedView.getTop() - y - textSizeHalf; + int[] coordsInParent = getCoordsInParent(); + if (useMovingOffset) { + movingOffsetX = cords[0] + textX + coordsInParent[0] - x; + } else { + movingOffsetX = 0; + } + movingOffsetY = cords[1] + textY + coordsInParent[1] - y - textSizeHalf; hideActions(); return true; } @@ -763,8 +779,9 @@ public boolean onTouchEvent(MotionEvent event) { int[] cords = offsetToCord(selectionEnd); float textSizeHalf = getLineHeight() / 2; - movingOffsetX = cords[0] + textX + selectedView.getX() - x; - movingOffsetY = cords[1] + textY + selectedView.getTop() - y - textSizeHalf; + int[] coordsInParent = getCoordsInParent(); + movingOffsetX = cords[0] + textX + coordsInParent[0] - x; + movingOffsetY = cords[1] + textY + coordsInParent[1] - y - textSizeHalf; showMagnifier(lastX); hideActions(); return true; @@ -799,15 +816,16 @@ public boolean onTouchEvent(MotionEvent event) { fillLayoutForOffset(selectionEnd, layoutBlock); } - StaticLayout oldTextLayout = layoutBlock.layout; + Layout oldTextLayout = layoutBlock.layout; if (oldTextLayout == null) { return true; } float oldYoffset = layoutBlock.yOffset; Cell oldSelectedView = selectedView; - y -= selectedView.getTop(); - x -= selectedView.getX(); + int[] coordsInParent = getCoordsInParent(); + y -= coordsInParent[1]; + x -= coordsInParent[0]; boolean canScrollDown = event.getY() - touchSlop > parentView.getMeasuredHeight() - getParentBottomPadding() && (multiselect || selectedView.getBottom() > parentView.getMeasuredHeight() - getParentBottomPadding()); boolean canScrollUp = event.getY() < ((View) parentView.getParent()).getTop() + getParentTopPadding() && (multiselect || selectedView.getTop() < getParentTopPadding()); @@ -852,10 +870,10 @@ public boolean onTouchEvent(MotionEvent event) { CharSequence text = getText(selectedView, false); fillLayoutForOffset(newSelection, layoutBlock); - StaticLayout layoutOld = layoutBlock.layout; + Layout layoutOld = layoutBlock.layout; fillLayoutForOffset(selectionStart, layoutBlock); - StaticLayout layoutNew = layoutBlock.layout; + Layout layoutNew = layoutBlock.layout; if (layoutOld == null || layoutNew == null) { return true; @@ -954,10 +972,10 @@ public boolean onTouchEvent(MotionEvent event) { fillLayoutForOffset(newSelection, layoutBlock); - StaticLayout layoutOld = layoutBlock.layout; + Layout layoutOld = layoutBlock.layout; fillLayoutForOffset(selectionEnd, layoutBlock); - StaticLayout layoutNew = layoutBlock.layout; + Layout layoutNew = layoutBlock.layout; if (layoutOld == null || layoutNew == null) { return true; @@ -1037,7 +1055,7 @@ public boolean onTouchEvent(MotionEvent event) { movingHandle = false; movingDirectionSettling = false; isOneTouch = false; - if (isSelectionMode()) { + if (isInSelectionMode()) { showActions(); showHandleViews(); } @@ -1053,7 +1071,7 @@ public boolean onTouchEvent(MotionEvent event) { @Override protected void onDraw(Canvas canvas) { - if (!isSelectionMode()) return; + if (!isInSelectionMode()) return; int handleViewSize = AndroidUtilities.dp(22); int count = 0; @@ -1061,8 +1079,10 @@ protected void onDraw(Canvas canvas) { pickEndView(); if (selectedView != null) { canvas.save(); - float yOffset = selectedView.getY() + textY; - float xOffset = selectedView.getX() + textX; + int[] coordsInParent = getCoordsInParent(); + float yOffset = coordsInParent[1] + textY; + float xOffset = coordsInParent[0] + textX; + canvas.translate(xOffset, yOffset); MessageObject msg = selectedView instanceof ChatMessageCell ? ((ChatMessageCell) selectedView).getMessageObject() : null; @@ -1076,7 +1096,7 @@ protected void onDraw(Canvas canvas) { if (selectionEnd >= 0 && selectionEnd <= len) { fillLayoutForOffset(selectionEnd, layoutBlock); - StaticLayout layout = layoutBlock.layout; + Layout layout = layoutBlock.layout; if (layout != null) { int end = selectionEnd - layoutBlock.charOffset; int textLen = layout.getText().length(); @@ -1133,15 +1153,16 @@ protected void onDraw(Canvas canvas) { pickStartView(); if (selectedView != null) { canvas.save(); - float yOffset = selectedView.getY() + textY; - float xOffset = selectedView.getX() + textX; + int[] coordsInParent = getCoordsInParent(); + float yOffset = coordsInParent[1] + textY; + float xOffset = coordsInParent[0] + textX; canvas.translate(xOffset, yOffset); int len = getText(selectedView, false).length(); if (selectionStart >= 0 && selectionStart <= len) { fillLayoutForOffset(selectionStart, layoutBlock); - StaticLayout layout = layoutBlock.layout; + Layout layout = layoutBlock.layout; if (layout != null) { int start = selectionStart - layoutBlock.charOffset; int line = layout.getLineForOffset(start); @@ -1222,6 +1243,67 @@ protected void onDraw(Canvas canvas) { invalidate(); } } + + public boolean isTouched() { + return movingHandle; + } + + public void checkCancel(float lastMotionX, float lastMotionY, boolean inParent) { + if (!inParent) { + int[] coordsInParent = getCoordsInParent(); + lastMotionY += coordsInParent[1] + textY; + } + if (!movingHandle && (lastMotionY < startArea.top - AndroidUtilities.dp(8) || lastMotionY > endArea.bottom + AndroidUtilities.dp(8))) { + clear(); + } + } + + float cancelPressedX, cancelPressedY; + public void checkCancelAction(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + cancelPressedX = ev.getX(); + cancelPressedY = ev.getY(); + } else if (Math.abs(ev.getX() - cancelPressedX) < AndroidUtilities.touchSlop && Math.abs(ev.getY() - cancelPressedY) < AndroidUtilities.touchSlop && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP)) { + checkCancel(ev.getX(), ev.getY(), true); + } + } + + @Override + public void invalidate() { + super.invalidate(); + if (invalidateParent && parentView != null) { + parentView.invalidate(); + } + } + } + + private int[] getCoordsInParent() { + View child = (View) selectedView; + int yOffset = 0; + int xOffset = 0; + if (child != null && parentView != null) { + while (child != parentView) { + if (child == null) { + xOffset = 0; + yOffset = 0; + break; + } + yOffset += child.getY(); + xOffset += child.getX(); + if (child instanceof NestedScrollView) { + yOffset -= child.getScrollY(); + xOffset -= child.getScrollX(); + } + if (child.getParent() instanceof View) { + child = (View) child.getParent(); + } else { + xOffset = 0; + yOffset = 0; + break; + } + } + } + return new int[] {xOffset, yOffset}; } protected void jumpToLine(int newSelection, int nextWhitespace, boolean viewChanged, float newYoffset, float oldYoffset, Cell oldSelectedView) { @@ -1333,7 +1415,7 @@ private void updateTranslateButton(Menu menu) { @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return true; } switch (item.getItemId()) { @@ -1396,17 +1478,18 @@ public void onDestroyActionMode(ActionMode mode) { @Override public void onGetContentRect(ActionMode mode, View view, Rect outRect) { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return; } pickStartView(); int x1 = 0; int y1 = 1; + int[] coordsInParent = getCoordsInParent(); if (selectedView != null) { int lineHeight = -getLineHeight(); int[] coords = offsetToCord(selectionStart); x1 = coords[0] + textX; - y1 = (int) (coords[1] + textY + selectedView.getY()) + lineHeight / 2 - AndroidUtilities.dp(4); + y1 = (int) (coords[1] + textY + coordsInParent[1]) + lineHeight / 2 - AndroidUtilities.dp(4); if (y1 < 1) y1 = 1; } @@ -1428,7 +1511,7 @@ public void onGetContentRect(ActionMode mode, View view, Rect outRect) { } private void copyText() { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return; } CharSequence str = getSelectedText(); @@ -1444,7 +1527,7 @@ private void copyText() { } private void translateText() { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return; } CharSequence str = getSelectedText(); @@ -1464,7 +1547,7 @@ protected CharSequence getSelectedText() { protected int[] offsetToCord(int offset) { fillLayoutForOffset(offset, layoutBlock); - StaticLayout layout = layoutBlock.layout; + Layout layout = layoutBlock.layout; int blockOffset = offset - layoutBlock.charOffset; if (layout == null || blockOffset < 0 || blockOffset > layout.getText().length()) { return tmpCoord; @@ -1477,7 +1560,7 @@ protected int[] offsetToCord(int offset) { return tmpCoord; } - protected void drawSelection(Canvas canvas, StaticLayout layout, int selectionStart, int selectionEnd, boolean hasStart, boolean hasEnd) { + protected void drawSelection(Canvas canvas, Layout layout, int selectionStart, int selectionEnd, boolean hasStart, boolean hasEnd) { selectionPath.reset(); selectionHandlePath.reset(); final float R = cornerRadius * 1.65f; @@ -1574,7 +1657,7 @@ protected void drawSelection(Canvas canvas, StaticLayout layout, int selectionSt } private final ScalablePath tempPath2 = new ScalablePath(); - private void drawLine(StaticLayout layout, int line, int start, int end, boolean padAtStart, boolean padAtEnd) { + private void drawLine(Layout layout, int line, int start, int end, boolean padAtStart, boolean padAtEnd) { tempPath2.reset(); layout.getSelectionPath(start, end, tempPath2); @@ -1607,11 +1690,11 @@ private void drawLine(StaticLayout layout, int line, int start, int end, boolean } } - private static class LayoutBlock { + public static class LayoutBlock { public int charOffset; - StaticLayout layout; - float yOffset; - float xOffset; + public Layout layout; + public float yOffset; + public float xOffset; } @@ -1634,6 +1717,109 @@ protected void fillLayoutForOffset(int offset, LayoutBlock layoutBlock) { protected abstract void onTextSelected(Cell newView, Cell oldView); + public static class SimpleTextSelectionHelper extends TextSelectionHelper { + + SimpleSelectabeleView selectabeleView; + + public SimpleTextSelectionHelper(SimpleSelectabeleView selectabeleView, Theme.ResourcesProvider resourcesProvider) { + this.selectabeleView = selectabeleView; + this.resourcesProvider = resourcesProvider; + } + + public void setSelectabeleView(SimpleSelectabeleView selectabeleView) { + this.selectabeleView = selectabeleView; + } + + @Override + protected CharSequence getText(SimpleSelectabeleView view, boolean maybe) { + return view.getText(); + } + + @Override + protected int getCharOffsetFromCord(int x, int y, int offsetX, int offsetY, SimpleSelectabeleView view, boolean maybe) { + if (y < 0) { + y = 1; + } + float yOffset = 0; + Layout lastLayout = view.getStaticTextLayout(); + if (y > yOffset + lastLayout.getLineBottom(lastLayout.getLineCount() - 1)) { + y = (int) (yOffset + lastLayout.getLineBottom(lastLayout.getLineCount() - 1) - 1); + } + + if (layoutBlock.layout == null) { + return -1; + } + + Layout layout = layoutBlock.layout; + x -= layoutBlock.xOffset; + + int line = -1; + for (int i = 0; i < layout.getLineCount(); i++) { + if (y > layoutBlock.yOffset + layout.getLineTop(i) && y < layoutBlock.yOffset + layout.getLineBottom(i)) { + line = i; + break; + } + } + if (line >= 0) { + int k = layoutBlock.charOffset + layout.getOffsetForHorizontal(line, x);; + return k; + } + + return -1; + } + + @Override + protected void fillLayoutForOffset(int offset, LayoutBlock layoutBlock, boolean maybe) { + layoutBlock.layout = selectabeleView.getStaticTextLayout(); + layoutBlock.xOffset = layoutBlock.yOffset = 0; + layoutBlock.charOffset = 0; + } + + @Override + protected int getLineHeight() { + Layout layout = selectabeleView.getStaticTextLayout(); + int lineHeight = layout.getLineBottom(0) - layout.getLineTop(0); + return lineHeight; + } + + @Override + protected void onTextSelected(SimpleSelectabeleView newView, SimpleSelectabeleView oldView) { + + } + + public void update(float textX, float textY) { + Layout layout = selectabeleView.getStaticTextLayout(); + if (layout == null) { + textArea.setEmpty(); + maybeSelectedView = null; + } else { + maybeSelectedView = selectabeleView; + maybeTextX = (int) textX; + maybeTextY = (int) textY; + layoutBlock.layout = layout; + layoutBlock.xOffset = textX; + layoutBlock.yOffset = textY; + layoutBlock.charOffset = 0; + textArea.set( + (int) textX, (int) textY, + (int) (textX + layout.getWidth()), (int) (textY + layout.getHeight()) + ); + } + } + + public void draw(Canvas canvas) { + Layout layout = selectabeleView.getStaticTextLayout(); + int color = Theme.getColor(Theme.key_chat_textSelectBackground, resourcesProvider); + selectionPaint.setColor(color); + selectionHandlePaint.setColor(color); + drawSelection(canvas, layout, selectionStart, selectionEnd, true, true); + } + + public boolean isCurrent(SimpleSelectabeleView view) { + return this.selectabeleView == view; + } + } + public static class ChatListTextSelectionHelper extends TextSelectionHelper { SparseArray animatorSparseArray = new SparseArray<>(); @@ -1817,7 +2003,7 @@ protected int getCharOffsetFromCord(int x, int y, int offsetX, int offsetY, Chat return -1; } - StaticLayout layout = layoutBlock.layout; + Layout layout = layoutBlock.layout; x -= layoutBlock.xOffset; @@ -2476,7 +2662,7 @@ protected void onNewViewSelected(ArticleSelectableView oldView, ArticleSelectabl boolean startPeek; protected void pickEndView() { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return; } startPeek = false; @@ -2518,7 +2704,7 @@ protected void pickEndView() { } protected void pickStartView() { - if (!isSelectionMode()) { + if (!isInSelectionMode()) { return; } startPeek = true; @@ -2769,6 +2955,13 @@ public interface ArticleSelectableView extends SelectableView { void fillTextLayoutBlocks(ArrayList blocks); } + public interface SimpleSelectabeleView extends SelectableView { + + CharSequence getText(); + + Layout getStaticTextLayout(); + } + public interface SelectableView { int getBottom(); @@ -2886,10 +3079,10 @@ public int getParentBottomPadding() { } protected int getThemedColor(int key) { - return Theme.getColor(key); + return Theme.getColor(key, resourcesProvider); } protected Theme.ResourcesProvider getResourcesProvider() { - return null; + return resourcesProvider; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 163b4728f8..2d716c02bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -121,6 +121,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ChatMessageSharedResources; import org.telegram.messenger.ChatMessagesMetadataController; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; @@ -746,6 +747,13 @@ public int getColor(int key) { private boolean chatListViewAttached; public boolean forceDisallowApplyWallpeper; public boolean forceDisallowRedrawThemeDescriptions; + private boolean waitingForGetDifference; + private int initialMessagesSize; + private boolean loadInfo; + private boolean historyPreloaded; + private int migrated_to; + private boolean firstMessagesLoaded; + private Runnable closeInstantCameraAnimation; { skeletonOutlinePaint.setStyle(Paint.Style.STROKE); @@ -864,6 +872,7 @@ public void run() { private TextSelectionHint textSelectionHint; private boolean textSelectionHintWasShowed; private float lastTouchY; + ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate; private ChatMessageCell dummyMessageCell; private FireworksOverlay fireworksOverlay; @@ -1032,6 +1041,7 @@ public boolean needPostpone(int id, int currentAccount, Object[] args) { public float drawingChatLisViewYoffset; public int blurredViewTopOffset; public int blurredViewBottomOffset; + public ChatMessageSharedResources sharedResources; private ValueAnimator searchExpandAnimator; private float searchExpandProgress; @@ -1321,7 +1331,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolea RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { - if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isSelectionMode() || inPreviewMode) { + if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isInSelectionMode() || inPreviewMode) { return false; } wasManualScroll = true; @@ -2090,11 +2100,11 @@ public boolean onFragmentCreate() { } reportType = arguments.getInt("report", -1); pulled = arguments.getBoolean("pulled", false); - boolean historyPreloaded = arguments.getBoolean("historyPreloaded", false); + historyPreloaded = arguments.getBoolean("historyPreloaded", false); if (highlightMessageId != 0 && highlightMessageId != Integer.MAX_VALUE) { startLoadFromMessageId = highlightMessageId; } - int migrated_to = arguments.getInt("migrated_to", 0); + migrated_to = arguments.getInt("migrated_to", 0); scrollToTopOnResume = arguments.getBoolean("scrollToTopOnResume", false); needRemovePreviousSameChatActivity = arguments.getBoolean("need_remove_previous_same_chat_activity", true); justCreatedChat = arguments.getBoolean("just_created_chat", false); @@ -2121,7 +2131,17 @@ public boolean onFragmentCreate() { } dialog_id = -chatId; if (ChatObject.isChannel(currentChat)) { - getMessagesController().startShortPoll(currentChat, classGuid, false); + if (ChatObject.isNotInChat(currentChat)) { + waitingForGetDifference = true; + getMessagesController().startShortPoll(currentChat, classGuid, false, isGettingDifference -> { + waitingForGetDifference = isGettingDifference; + if (!waitingForGetDifference) { + firstLoadMessages(); + } + }); + } else { + getMessagesController().startShortPoll(currentChat, classGuid, false); + } } } else if (userId != 0) { currentUser = getMessagesController().getUser(userId); @@ -2301,6 +2321,7 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.dialogIsTranslatable); getNotificationCenter().addObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().addObserver(this, NotificationCenter.messageTranslating); + getNotificationCenter().addObserver(this, NotificationCenter.onReceivedChannelDifference); super.onFragmentCreate(); @@ -2351,7 +2372,7 @@ public boolean onFragmentCreate() { } } - boolean loadInfo = false; + loadInfo = false; if (currentChat != null) { chatInfo = getMessagesController().getChatFull(currentChat.id); groupCall = getMessagesController().getGroupCall(currentChat.id, true); @@ -2382,35 +2403,15 @@ public boolean onFragmentCreate() { checkDispatchHideSkeletons(false); } if (chatMode != MODE_PINNED && !forceHistoryEmpty) { - waitingForLoad.add(lastLoadIndex); - int initialMessagesSize; if (SharedConfig.deviceIsHigh()) { initialMessagesSize = (isThreadChat() && !isTopic) ? 30 : 25; } else { initialMessagesSize = (isThreadChat() && !isTopic) ? 20 : 15; } - if (startLoadFromDate != 0) { - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, startLoadFromDate, true, 0, classGuid, 4, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - } else if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId || isTopic)) { - startLoadFromMessageIdSaved = startLoadFromMessageId; - if (migrated_to != 0) { - mergeDialogId = migrated_to; - getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - } - } else { - if (historyPreloaded) { - lastLoadIndex++; - } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - } + if (!waitingForGetDifference) { + firstLoadMessages(); } } - if (chatMode == 0 && !isThreadChat()) { - waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - } if (chatMode == 0) { if (userId != 0 && currentUser.bot) { @@ -2439,7 +2440,7 @@ public boolean onFragmentCreate() { if (chatInfo != null && chatInfo.linked_chat_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(chatInfo.linked_chat_id); if (chat != null && chat.megagroup) { - getMessagesController().startShortPoll(chat, classGuid, false); + getMessagesController().startShortPoll(chat, classGuid, false, null); } } @@ -2483,6 +2484,35 @@ public boolean onFragmentCreate() { return true; } + private void firstLoadMessages() { + if (firstMessagesLoaded) { + return; + } + firstMessagesLoaded = true; + waitingForLoad.add(lastLoadIndex); + if (startLoadFromDate != 0) { + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, startLoadFromDate, true, 0, classGuid, 4, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } else if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId || isTopic)) { + startLoadFromMessageIdSaved = startLoadFromMessageId; + if (migrated_to != 0) { + mergeDialogId = migrated_to; + getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } else { + getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } + } else { + if (historyPreloaded) { + lastLoadIndex++; + } else { + getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } + } + if (chatMode == 0 && !isThreadChat()) { + waitingForLoad.add(lastLoadIndex); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } + } + private void fillInviterId(boolean load) { if (currentChat == null || chatInfo == null || ChatObject.isNotInChat(currentChat) || currentChat.creator) { return; @@ -2568,6 +2598,7 @@ public void onFragmentDestroy() { if (chatAttachAlert != null) { chatAttachAlert.dismissInternal(); } + ContentPreviewViewer.getInstance().clearDelegate(contentPreviewViewerDelegate); getNotificationCenter().onAnimationFinish(transitionAnimationIndex); NotificationCenter.getGlobalInstance().onAnimationFinish(transitionAnimationGlobalIndex); getNotificationCenter().onAnimationFinish(scrollAnimationIndex); @@ -2656,6 +2687,7 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.dialogIsTranslatable); getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslating); + getNotificationCenter().removeObserver(this, NotificationCenter.onReceivedChannelDifference); if (currentEncryptedChat != null) { getNotificationCenter().removeObserver(this, NotificationCenter.didVerifyMessagesStickers); } @@ -2762,10 +2794,11 @@ public View createView(Context context) { actionBar.setSubtitleColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); } actionBarBackgroundPaint.setColor(getThemedColor(Theme.key_actionBarDefault)); + sharedResources = new ChatMessageSharedResources(context); if (chatMessageCellsCache.isEmpty()) { for (int a = 0; a < 15; a++) { - chatMessageCellsCache.add(new ChatMessageCell(context, true, themeDelegate)); + chatMessageCellsCache.add(new ChatMessageCell(context, true, sharedResources, themeDelegate)); } } for (int a = 1; a >= 0; a--) { @@ -3574,7 +3607,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } forceScrollToTop = false; - if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { textSelectionHelper.invalidate(); } isSkeletonVisible(); @@ -3837,7 +3870,7 @@ private void processTouchEvent(MotionEvent e) { currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && allowReplyOnOpenTopic || message.wasJustSent) || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat)) || - textSelectionHelper.isSelectionMode()) { + textSelectionHelper.isInSelectionMode()) { slidingView.setSlidingOffset(0); slidingView = null; return; @@ -5798,7 +5831,7 @@ protected void onScrolled(boolean atTop, boolean atBottom) { }; contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); - final ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { + contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, String query, Object parent, boolean notify, int scheduleDate) { chatActivityEnterView.onStickerSelected(sticker, query, parent, null, true, notify, scheduleDate); @@ -10342,7 +10375,7 @@ public boolean isKeyboardVisible() { } private void checkScrollForLoad(boolean scroll) { - if (chatLayoutManager == null || paused || chatAdapter.isFrozen) { + if (chatLayoutManager == null || paused || chatAdapter.isFrozen || waitingForGetDifference) { return; } int firstVisibleItem = RecyclerListView.NO_POSITION; @@ -10631,9 +10664,11 @@ private void searchLinks(final CharSequence charSequence, final boolean force) { } final MessagesController messagesController = getMessagesController(); Utilities.searchQueue.postRunnable(() -> { + boolean requestAnyway = false; if (linkSearchRequestId != 0) { getConnectionsManager().cancelRequest(linkSearchRequestId, true); linkSearchRequestId = 0; + requestAnyway = true; } ArrayList urls = null; CharSequence textToCheck; @@ -10668,7 +10703,7 @@ private void searchLinks(final CharSequence charSequence, final boolean force) { clear = false; } } - if (clear) { + if (clear && !requestAnyway) { return; } } @@ -12123,7 +12158,7 @@ private int getHeightForMessage(MessageObject object) { return 0; } if (dummyMessageCell == null) { - dummyMessageCell = new ChatMessageCell(getParentActivity(), true, themeDelegate); + dummyMessageCell = new ChatMessageCell(getParentActivity(), true, sharedResources, themeDelegate); } dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isBot = currentUser != null && currentUser.bot; @@ -12188,6 +12223,9 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa } public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean forceScroll, int forcePinnedMessageId, Runnable inCaseLoading) { + if (waitingForGetDifference) { + return; + } if (id == 0 || NotificationCenter.getInstance(currentAccount).isAnimationInProgress() || getParentActivity() == null) { if (NotificationCenter.getInstance(currentAccount).isAnimationInProgress()) { nextScrollToMessageId = id; @@ -12393,7 +12431,7 @@ private void updatePagedownButtonVisibility(boolean animated) { if (pagedownButton == null) { return; } - boolean show = canShowPagedownButton && !textSelectionHelper.isSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo(); + boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo(); if (show) { if (animated && (openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150)) { animated = false; @@ -12752,7 +12790,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { lastTouchY = ev.getY(); TextSelectionHelper.TextSelectionOverlay selectionOverlay = textSelectionHelper.getOverlayView(getContext()); ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); - if (textSelectionHelper.isSelectionMode() && textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { + if (textSelectionHelper.isInSelectionMode() && textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { return true; } else { ev.offsetLocation(selectionOverlay.getX(), selectionOverlay.getY()); @@ -12762,7 +12800,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { ev.setAction(MotionEvent.ACTION_CANCEL); } - if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isSelectionMode() && (ev.getY() < chatListView.getTop() || ev.getY() > chatListView.getBottom())) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isInSelectionMode() && (ev.getY() < chatListView.getTop() || ev.getY() > chatListView.getBottom())) { ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); if (textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { ev.offsetLocation(selectionOverlay.getX(), selectionOverlay.getY()); @@ -17897,10 +17935,12 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (newGroups != null) { for (int b = 0, N = newGroups.size(); b < N; b++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); - MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); - int index = messages.indexOf(messageObject); - if (index >= 0) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); + if (!groupedMessages.messages.isEmpty()) { + MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); + int index = messages.indexOf(messageObject); + if (index >= 0) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); + } } } } @@ -18319,6 +18359,12 @@ public void didReceivedNotification(int id, int account, final Object... args) { updateTopPanel(true); updateTranslateItemVisibility(); + } else if (id == NotificationCenter.onReceivedChannelDifference) { + final long channelId = (long) args[0]; + if (-channelId == dialog_id) { + waitingForGetDifference = false; + firstLoadMessages(); + } } } @@ -26240,7 +26286,7 @@ public boolean onBackPressed() { return false; } else if (checkRecordLocked(false)) { return false; - } else if (textSelectionHelper.isSelectionMode()) { + } else if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); return false; } else if (actionBar != null && actionBar.isActionModeShowed()) { @@ -26613,6 +26659,12 @@ public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo vid if (photoEntry == null) { return; } + if (videoEditedInfo != null && videoEditedInfo.roundVideo) { + AndroidUtilities.runOnUIThread(closeInstantCameraAnimation = () -> { + closeInstantCameraAnimation = null; + runCloseInstantCameraAnimation(); + }, 3000); + } fillEditingMediaWithCaption(photoEntry.caption, photoEntry.entities); if (photoEntry.isVideo) { if (videoEditedInfo != null) { @@ -26630,6 +26682,32 @@ public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo vid afterMessageSend(); } + private void runCloseInstantCameraAnimation() { + instantCameraView.cancelBlur(); + + final InstantCameraView.InstantViewCameraContainer cameraContainer = instantCameraView.getCameraContainer(); + AnimatorSet allAnimators = new AnimatorSet(); + allAnimators.playTogether( + ObjectAnimator.ofFloat(cameraContainer, View.SCALE_X, 0.5f), + ObjectAnimator.ofFloat(cameraContainer, View.SCALE_Y, 0.5f), + ObjectAnimator.ofFloat(cameraContainer, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(instantCameraView.getSwitchButtonView(), View.ALPHA, 0.0f), + ObjectAnimator.ofInt(instantCameraView.getPaint(), AnimationProperties.PAINT_ALPHA, 0), + ObjectAnimator.ofFloat(instantCameraView.getMuteImageView(), View.ALPHA, 0.0f) + ); + allAnimators.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (instantCameraView != null) { + instantCameraView.setIsMessageTransition(false); + instantCameraView.hideCamera(true); + instantCameraView.setVisibility(View.INVISIBLE); + } + } + }); + allAnimators.start(); + } + public void sendAnimatedEmoji(TLRPC.Document emoji, boolean notify, int scheduleDate) { if (emoji == null) { return; @@ -26781,7 +26859,7 @@ public void didReceivedNotification(int id, int account, Object... args) { }; NotificationCenter.getInstance(currentAccount).addObserver(observer, NotificationCenter.messagesDidLoad); Utilities.stageQueue.postRunnable(() -> { - getMessagesController().processLoadedMessages(historyFinal, historyFinal.messages.size(), dialogId, 0, 30, (highlightMsgId > 0 ? highlightMsgId : maxReadId), 0, false, commentsClassGuid, fnidFinal, 0, 0, 0, (highlightMsgId > 0 ? 3 : 2), true, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0, true, isTopic); + getMessagesController().processLoadedMessages(historyFinal, historyFinal.messages.size(), dialogId, 0, 30, (highlightMsgId > 0 ? highlightMsgId : maxReadId), 0, false, commentsClassGuid, fnidFinal, 0, 0, 0, (highlightMsgId > 0 ? 3 : 2), true, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0, true, isTopic, null); }); } else { openCommentsChat.run(); @@ -27757,7 +27835,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view = chatMessageCellsCache.get(0); chatMessageCellsCache.remove(0); } else { - view = new ChatMessageCell(mContext, true, themeDelegate); + view = new ChatMessageCell(mContext, true, sharedResources, themeDelegate); } ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setResourcesProvider(themeDelegate); @@ -28160,6 +28238,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { boolean applyAnimation = false; if (message.type == MessageObject.TYPE_ROUND_VIDEO && instantCameraView != null && instantCameraView.getTextureView() != null) { applyAnimation = true; + if (closeInstantCameraAnimation != null) { + AndroidUtilities.cancelRunOnUIThread(closeInstantCameraAnimation); + closeInstantCameraAnimation = null; + } messageCell.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index 3f3e17149f..bb080cba86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -503,11 +503,11 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b } }; imageReceiver.setAllowLoadingOnAttachedOnly(true); + if (cacheType == CACHE_TYPE_RENDERING_VIDEO) { + imageReceiver.ignoreNotifications = true; + } }; - if (cacheType == CACHE_TYPE_RENDERING_VIDEO) { - imageReceiver.ignoreNotifications = true; - } if (colorFilterToSet != null && canOverrideColor()) { imageReceiver.setColorFilter(colorFilterToSet); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index e6c8f890b5..2ee416349b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -23,17 +23,18 @@ import android.graphics.drawable.Animatable; import android.graphics.drawable.BitmapDrawable; import android.os.Build; -import android.util.Log; import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimatedFileDrawableStream; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.DispatchQueuePoolBackground; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.utils.BitmapsCache; import org.telegram.tgnet.TLRPC; @@ -48,6 +49,11 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, public boolean skipFrameUpdate; public long currentTime; + // canvas.drawPath lead to glitches + // clipPath not use antialias + private final boolean USE_BITMAP_SHADER = Build.VERSION.SDK_INT < 29; + private boolean PRERENDER_FRAME = true; + private static native long createDecoder(String src, int[] params, int account, long streamFileSize, Object readCallback, boolean preview); private static native void destroyDecoder(long ptr); @@ -259,26 +265,34 @@ public void run() { } loadFrameTask = null; - if (nextRenderingBitmap == null && nextRenderingBitmap2 == null) { + if (!PRERENDER_FRAME) { nextRenderingBitmap = backgroundBitmap; nextRenderingBitmapTime = backgroundBitmapTime; for (int i = 0; i < backgroundShader.length; i++) { nextRenderingShader[i] = backgroundShader[i]; } - } else if (nextRenderingBitmap == null) { - nextRenderingBitmap = nextRenderingBitmap2; - nextRenderingBitmapTime = nextRenderingBitmapTime2; - nextRenderingBitmap2 = backgroundBitmap; - nextRenderingBitmapTime2 = backgroundBitmapTime; - for (int i = 0; i < backgroundShader.length; i++) { - nextRenderingShader[i] = nextRenderingShader2[i]; - nextRenderingShader2[i] = backgroundShader[i]; - } } else { - nextRenderingBitmap2 = backgroundBitmap; - nextRenderingBitmapTime2 = backgroundBitmapTime; - for (int i = 0; i < backgroundShader.length; i++) { - nextRenderingShader2[i] = backgroundShader[i]; + if (nextRenderingBitmap == null && nextRenderingBitmap2 == null) { + nextRenderingBitmap = backgroundBitmap; + nextRenderingBitmapTime = backgroundBitmapTime; + for (int i = 0; i < backgroundShader.length; i++) { + nextRenderingShader[i] = backgroundShader[i]; + } + } else if (nextRenderingBitmap == null) { + nextRenderingBitmap = nextRenderingBitmap2; + nextRenderingBitmapTime = nextRenderingBitmapTime2; + nextRenderingBitmap2 = backgroundBitmap; + nextRenderingBitmapTime2 = backgroundBitmapTime; + for (int i = 0; i < backgroundShader.length; i++) { + nextRenderingShader[i] = nextRenderingShader2[i]; + nextRenderingShader2[i] = backgroundShader[i]; + } + } else { + nextRenderingBitmap2 = backgroundBitmap; + nextRenderingBitmapTime2 = backgroundBitmapTime; + for (int i = 0; i < backgroundShader.length; i++) { + nextRenderingShader2[i] = backgroundShader[i]; + } } } backgroundBitmap = null; @@ -394,7 +408,7 @@ public void run() { } catch (Throwable e) { FileLog.e(e); } - if (backgroundShader[0] == null && backgroundBitmap != null && hasRoundRadius()) { + if (USE_BITMAP_SHADER && backgroundShader[0] == null && backgroundBitmap != null && hasRoundRadius()) { backgroundShader[0] = new BitmapShader(backgroundBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } } @@ -467,6 +481,7 @@ public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, i public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, int streamLoadingPriority, TLRPC.Document document, ImageLocation location, Object parentObject, long seekTo, int account, boolean preview, int w, int h, BitmapsCache.CacheOptions cacheOptions) { path = file; + PRERENDER_FRAME = SharedConfig.deviceIsAboveAverage() && limitFps; streamFileSize = streamSize; this.streamLoadingPriority = streamLoadingPriority; currentAccount = account; @@ -503,6 +518,7 @@ public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, i public void setIsWebmSticker(boolean b) { isWebmSticker = b; + PRERENDER_FRAME = false; if (isWebmSticker) { useSharedQueue = true; } @@ -750,7 +766,7 @@ public int getDurationMs() { } private void scheduleNextGetFrame() { - if (loadFrameTask != null || (nextRenderingBitmap2 != null && nextRenderingBitmap != null) || !canLoadFrames() || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded) || parents.size() == 0 && !ignoreNoParent || generatingCache) { + if (loadFrameTask != null || ((!PRERENDER_FRAME || nextRenderingBitmap2 != null) && nextRenderingBitmap != null) || !canLoadFrames() || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded) || parents.size() == 0 && !ignoreNoParent || generatingCache) { return; } long ms = 0; @@ -874,33 +890,36 @@ public void drawInternal(Canvas canvas, boolean drawInBackground, long currentTi } if (hasRoundRadius()) { int index = drawInBackground ? threadIndex + 1 : 0; - if (renderingShader[index] == null) { - renderingShader[index] = new BitmapShader(renderingBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - } - paint.setShader(renderingShader[index]); - Matrix matrix = shaderMatrix[index]; - if (matrix == null) { - matrix = shaderMatrix[index] = new Matrix(); + if (USE_BITMAP_SHADER) { + if (renderingShader[index] == null) { + renderingShader[index] = new BitmapShader(renderingBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + } + paint.setShader(renderingShader[index]); + Matrix matrix = shaderMatrix[index]; + if (matrix == null) { + matrix = shaderMatrix[index] = new Matrix(); + } + matrix.reset(); + matrix.setTranslate(rect.left, rect.top); + if (metaData[2] == 90) { + matrix.preRotate(90); + matrix.preTranslate(0, -rect.width()); + } else if (metaData[2] == 180) { + matrix.preRotate(180); + matrix.preTranslate(-rect.width(), -rect.height()); + } else if (metaData[2] == 270) { + matrix.preRotate(270); + matrix.preTranslate(-rect.height(), 0); + } + matrix.preScale(scaleX, scaleY); + + renderingShader[index].setLocalMatrix(matrix); } + Path path = roundPath[index]; if (path == null) { path = roundPath[index] = new Path(); } - matrix.reset(); - matrix.setTranslate(rect.left, rect.top); - if (metaData[2] == 90) { - matrix.preRotate(90); - matrix.preTranslate(0, -rect.width()); - } else if (metaData[2] == 180) { - matrix.preRotate(180); - matrix.preTranslate(-rect.width(), -rect.height()); - } else if (metaData[2] == 270) { - matrix.preRotate(270); - matrix.preTranslate(-rect.height(), 0); - } - matrix.preScale(scaleX, scaleY); - - renderingShader[index].setLocalMatrix(matrix); if (invalidatePath || drawInBackground) { if (!drawInBackground) { invalidatePath = false; @@ -909,29 +928,39 @@ public void drawInternal(Canvas canvas, boolean drawInBackground, long currentTi radii[a * 2] = roundRadius[a]; radii[a * 2 + 1] = roundRadius[a]; } - path.reset(); + path.rewind(); path.addRoundRect(drawInBackground ? rect : actualDrawRect, radii, Path.Direction.CW); - path.close(); } - canvas.drawPath(path, paint); - } else { - canvas.translate(rect.left, rect.top); - if (metaData[2] == 90) { - canvas.rotate(90); - canvas.translate(0, -rect.width()); - } else if (metaData[2] == 180) { - canvas.rotate(180); - canvas.translate(-rect.width(), -rect.height()); - } else if (metaData[2] == 270) { - canvas.rotate(270); - canvas.translate(-rect.height(), 0); + if (USE_BITMAP_SHADER) { + canvas.drawPath(path, paint); + } else { + canvas.save(); + canvas.clipPath(path); + drawBitmap(rect, paint, canvas, scaleX, scaleY); + canvas.restore(); } - canvas.scale(scaleX, scaleY); - canvas.drawBitmap(renderingBitmap, 0, 0, paint); + } else { + drawBitmap(rect, paint, canvas, scaleX, scaleY); } } } + private void drawBitmap(RectF rect, Paint paint, Canvas canvas, float sx, float sy) { + canvas.translate(rect.left, rect.top); + if (metaData[2] == 90) { + canvas.rotate(90); + canvas.translate(0, -rect.width()); + } else if (metaData[2] == 180) { + canvas.rotate(180); + canvas.translate(-rect.width(), -rect.height()); + } else if (metaData[2] == 270) { + canvas.rotate(270); + canvas.translate(-rect.height(), 0); + } + canvas.scale(sx, sy); + canvas.drawBitmap(renderingBitmap, 0, 0, paint); + } + public long getLastFrameTimestamp() { return lastTimeStamp; } @@ -1067,6 +1096,9 @@ public Bitmap getNextFrame() { public void setLimitFps(boolean limitFps) { this.limitFps = limitFps; + if (limitFps) { + PRERENDER_FRAME = false; + } } public ArrayList getParents() { @@ -1225,4 +1257,12 @@ public void updateCurrentFrame(long now, boolean b) { public int getFps() { return metaData[5]; } + + public int getRenderingWidth() { + return renderingWidth; + } + + public int getRenderingHeight() { + return renderingHeight; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java index d55c7671e1..9e61dfa0a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java @@ -45,14 +45,14 @@ public class CacheChart extends View { private RectF chartBounds = new RectF(); private RectF chartInnerBounds = new RectF(); - private static final int DEFAULT_SECTIONS_COUNT = 9; + private static final int DEFAULT_SECTIONS_COUNT = 10; private static final int[] DEFAULT_COLORS = new int[] { Theme.key_statisticChartLine_lightblue, Theme.key_statisticChartLine_blue, Theme.key_statisticChartLine_green, - Theme.key_statisticChartLine_red, + Theme.key_statisticChartLine_purple, Theme.key_statisticChartLine_lightgreen, - Theme.key_statisticChartLine_indigo, + Theme.key_statisticChartLine_red, Theme.key_statisticChartLine_orange, Theme.key_statisticChartLine_cyan, Theme.key_statisticChartLine_purple, @@ -65,7 +65,7 @@ public class CacheChart extends View { R.raw.cache_documents, R.raw.cache_music, R.raw.cache_videos, - R.raw.cache_other, + R.raw.cache_music, R.raw.cache_stickers, R.raw.cache_profile_photos, R.raw.cache_other, @@ -705,7 +705,7 @@ public void setSegments(long totalSize, boolean animated, SegmentSize ...segment k++; } - String[] fileSize = AndroidUtilities.formatFileSize(segmentsSum).split(" "); + String[] fileSize = AndroidUtilities.formatFileSize(segmentsSum, true, true).split(" "); String top = fileSize.length > 0 ? fileSize[0] : ""; if (top.length() >= 4 && segmentsSum < 1024L * 1024L * 1024L) { top = top.split("\\.")[0]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index cfa816d7b9..36730d03c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -5185,7 +5185,11 @@ public void updateFieldHint(boolean animated) { return; } else { messageEditText.setEnabled(true); - messageEditText.setInputType(commonInputType); + if (messageEditText.getInputType() != commonInputType) { + messageEditText.setInputType(commonInputType); + } else { + + } } if (replyingMessageObject != null && replyingMessageObject.messageOwner.reply_markup != null && !TextUtils.isEmpty(replyingMessageObject.messageOwner.reply_markup.placeholder)) { messageEditText.setHintText(replyingMessageObject.messageOwner.reply_markup.placeholder, animated); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 789826a8ed..e09a5cb363 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -5738,6 +5738,7 @@ protected void onDetachedFromWindow() { if (colorPickerView != null && colorPickerView.isShowing()) { colorPickerView.dismiss(); } + ContentPreviewViewer.getInstance().clearDelegate(contentPreviewViewerDelegate); } private void checkDocuments(boolean isGif) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java index 5ef44b979a..3d6d2e442c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java @@ -29,6 +29,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ChatMessageSharedResources; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; @@ -91,6 +92,7 @@ public interface ResourcesDelegate extends Theme.ResourcesProvider { ArrayList actionItems = new ArrayList<>(); Rect rect = new Rect(); + ChatMessageSharedResources sharedResources; private boolean firstLayout = true; ValueAnimator offsetsAnimator; @@ -116,6 +118,7 @@ public void run() { @SuppressLint("ClickableViewAccessibility") public ForwardingPreviewView(@NonNull Context context, ForwardingMessagesParams params, TLRPC.User user, TLRPC.Chat chat, int currentAccount, ResourcesDelegate resourcesProvider) { super(context); + sharedResources = new ChatMessageSharedResources(context); this.currentAccount = currentAccount; currentUser = user; currentChat = chat; @@ -976,10 +979,11 @@ public boolean isShowing() { } private class Adapter extends RecyclerView.Adapter { + @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), false, resourcesProvider); + ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), false, sharedResources, resourcesProvider); return new RecyclerListView.Holder(chatMessageCell); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java index 61377e4dd9..fa4a45f46e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -242,7 +242,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter @SuppressLint("ClickableViewAccessibility") public InstantCameraView(Context context, Delegate delegate, Theme.ResourcesProvider resourcesProvider) { super(context); - WRITE_TO_FILE_IN_BACKGROUND = SharedConfig.deviceIsAboveAverage(); + WRITE_TO_FILE_IN_BACKGROUND = false;//SharedConfig.deviceIsAboveAverage(); this.resourcesProvider = resourcesProvider; parentView = delegate.getFragmentView(); setWillNotDraw(false); @@ -515,20 +515,6 @@ protected void onDraw(Canvas canvas) { canvas.drawArc(rect, -90, 360 * progress, false, paint); canvas.restore(); } - if (Theme.chat_roundVideoShadow != null) { - int x1 = (int) x - AndroidUtilities.dp(3); - int y1 = (int) y - AndroidUtilities.dp(2); - canvas.save(); - if (isMessageTransition) { - canvas.scale(cameraContainer.getScaleX(), cameraContainer.getScaleY(), x, y); - } else { - canvas.scale(cameraContainer.getScaleX(), cameraContainer.getScaleY(), x + textureViewSize / 2f, y + textureViewSize / 2f); - } - Theme.chat_roundVideoShadow.setAlpha((int) (cameraContainer.getAlpha() * 255)); - Theme.chat_roundVideoShadow.setBounds(x1, y1, x1 + textureViewSize + AndroidUtilities.dp(6), y1 + textureViewSize + AndroidUtilities.dp(6)); - Theme.chat_roundVideoShadow.draw(canvas); - canvas.restore(); - } } @Override @@ -629,7 +615,7 @@ public boolean delete() { AutoDeleteMediaTask.lockFile(cameraFile); if (BuildVars.LOGS_ENABLED) { - FileLog.d("show round camera " + cameraFile.getAbsolutePath()); + FileLog.d("InstantCamera show round camera " + cameraFile.getAbsolutePath()); } textureView = new TextureView(getContext()); @@ -637,14 +623,14 @@ public boolean delete() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("camera surface available"); + FileLog.d("InstantCamera camera surface available"); } if (cameraThread == null && surface != null) { if (cancelled) { return; } if (BuildVars.LOGS_ENABLED) { - FileLog.d("start create thread"); + FileLog.d("InstantCamera start create thread"); } cameraThread = new CameraGLThread(surface, width, height); } @@ -1014,7 +1000,7 @@ private boolean initCamera() { } } if (BuildVars.LOGS_ENABLED) { - FileLog.d("preview w = " + previewSize.mWidth + " h = " + previewSize.mHeight); + FileLog.d("InstantCamera preview w = " + previewSize.mWidth + " h = " + previewSize.mHeight); } return true; } @@ -1099,7 +1085,7 @@ private void createCamera(final SurfaceTexture surfaceTexture) { return; } if (BuildVars.LOGS_ENABLED) { - FileLog.d("create camera session"); + FileLog.d("InstantCamera create camera session"); } surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); @@ -1112,7 +1098,7 @@ private void createCamera(final SurfaceTexture surfaceTexture) { Camera.Size size = cameraSession.getCurrentPreviewSize(); if (size.width != previewSize.getWidth() || size.height != previewSize.getHeight()) { previewSize = new Size(size.width, size.height); - FileLog.d("change preview size to w = " + previewSize.getWidth() + " h = " + previewSize.getHeight()); + FileLog.d("InstantCamera change preview size to w = " + previewSize.getWidth() + " h = " + previewSize.getHeight()); } } catch (Exception e) { FileLog.e(e); @@ -1122,14 +1108,14 @@ private void createCamera(final SurfaceTexture surfaceTexture) { Camera.Size size = cameraSession.getCurrentPictureSize(); if (size.width != pictureSize.getWidth() || size.height != pictureSize.getHeight()) { pictureSize = new Size(size.width, size.height); - FileLog.d("change picture size to w = " + pictureSize.getWidth() + " h = " + pictureSize.getHeight()); + FileLog.d("InstantCamera change picture size to w = " + pictureSize.getWidth() + " h = " + pictureSize.getHeight()); updateScale = true; } } catch (Exception e) { FileLog.e(e); } if (BuildVars.LOGS_ENABLED) { - FileLog.d("camera initied"); + FileLog.d("InstantCamera camera initied"); } cameraSession.setInitied(); if (updateScale) { @@ -1298,20 +1284,20 @@ private void updateScale() { scaleX = height / (float) surfaceWidth; scaleY = 1.0f; } - FileLog.d("camera scaleX = " + scaleX + " scaleY = " + scaleY); + FileLog.d("InstantCamera camera scaleX = " + scaleX + " scaleY = " + scaleY); } private boolean initGL() { if (BuildVars.LOGS_ENABLED) { - FileLog.d("start init gl"); + FileLog.d("InstantCamera start init gl"); } egl10 = (EGL10) EGLContext.getEGL(); eglDisplay = egl10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (eglDisplay == EGL10.EGL_NO_DISPLAY) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglGetDisplay failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera eglGetDisplay failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; @@ -1320,7 +1306,7 @@ private boolean initGL() { int[] version = new int[2]; if (!egl10.eglInitialize(eglDisplay, version)) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglInitialize failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera eglInitialize failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; @@ -1341,7 +1327,7 @@ private boolean initGL() { EGLConfig eglConfig; if (!egl10.eglChooseConfig(eglDisplay, configSpec, configs, 1, configsCount)) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglChooseConfig failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera eglChooseConfig failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; @@ -1349,7 +1335,7 @@ private boolean initGL() { eglConfig = configs[0]; } else { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglConfig not initialized"); + FileLog.e("InstantCamera eglConfig not initialized"); } finish(); return false; @@ -1359,7 +1345,7 @@ private boolean initGL() { eglContext = egl10.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); if (eglContext == null) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglCreateContext failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera eglCreateContext failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; @@ -1374,14 +1360,14 @@ private boolean initGL() { if (eglSurface == null || eglSurface == EGL10.EGL_NO_SURFACE) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("createWindowSurface failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera createWindowSurface failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; } if (!egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.e("InstantCamera eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } finish(); return false; @@ -1423,7 +1409,7 @@ private boolean initGL() { GLES20.glGetProgramiv(drawProgram, GLES20.GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] == 0) { if (BuildVars.LOGS_ENABLED) { - FileLog.e("failed link shader"); + FileLog.e("InstantCamera failed link shader"); } GLES20.glDeleteProgram(drawProgram); drawProgram = 0; @@ -1435,7 +1421,7 @@ private boolean initGL() { } } else { if (BuildVars.LOGS_ENABLED) { - FileLog.e("failed creating shader"); + FileLog.e("InstantCamera failed creating shader"); } finish(); return false; @@ -1454,7 +1440,7 @@ private boolean initGL() { cameraSurface.setOnFrameAvailableListener(surfaceTexture -> requestRender()); createCamera(cameraSurface); if (BuildVars.LOGS_ENABLED) { - FileLog.e("gl initied"); + FileLog.e("InstantCamera gl initied"); } return true; @@ -1469,6 +1455,19 @@ public void reinitForNewCamera() { } public void finish() { + if (cameraSurface != null) { + cameraSurface.release(); + cameraSurface = null; + } + if (eglSurface != null && eglContext != null) { + if (!eglContext.equals(egl10.eglGetCurrentContext()) || !eglSurface.equals(egl10.eglGetCurrentSurface(EGL10.EGL_DRAW))) { + egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); + } + if (cameraTexture[0] != 0) { + GLES20.glDeleteTextures(1, cameraTexture, 0); + cameraTexture[0] = 0; + } + } if (eglSurface != null) { egl10.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); egl10.eglDestroySurface(eglDisplay, eglSurface); @@ -1571,7 +1570,7 @@ public void handleMessage(Message inputMessage) { case DO_REINIT_MESSAGE: { if (!egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); + FileLog.d("InstantCamera eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError())); } return; } @@ -1618,7 +1617,7 @@ public void handleMessage(Message inputMessage) { } case DO_SETSESSION_MESSAGE: { if (BuildVars.LOGS_ENABLED) { - FileLog.d("set gl rednderer session"); + FileLog.d("InstantCamera set gl rednderer session"); } CameraSession newSession = (CameraSession) inputMessage.obj; if (currentSession == newSession) { @@ -1676,7 +1675,7 @@ public void handleMessage(Message inputMessage) { case MSG_START_RECORDING: { try { if (BuildVars.LOGS_ENABLED) { - FileLog.e("start encoder"); + FileLog.e("InstantCamera start encoder"); } encoder.prepareEncoder(); } catch (Exception e) { @@ -1688,7 +1687,7 @@ public void handleMessage(Message inputMessage) { } case MSG_STOP_RECORDING: { if (BuildVars.LOGS_ENABLED) { - FileLog.e("stop encoder"); + FileLog.e("InstantCamera stop encoder"); } encoder.handleStopRecording(inputMessage.arg1); break; @@ -1907,6 +1906,9 @@ public void run() { public void startRecording(File outputFile, android.opengl.EGLContext sharedContext) { int resolution = MessagesController.getInstance(currentAccount).roundVideoSize; int bitrate = MessagesController.getInstance(currentAccount).roundVideoBitrate * 1024; + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + }); videoFile = outputFile; videoWidth = resolution; @@ -1931,8 +1933,10 @@ public void startRecording(File outputFile, android.opengl.EGLContext sharedCont } } - fileWriteQueue = new DispatchQueue("IVR_FileWriteQueue"); - fileWriteQueue.setPriority(Thread.MAX_PRIORITY); + if (WRITE_TO_FILE_IN_BACKGROUND) { + fileWriteQueue = new DispatchQueue("IVR_FileWriteQueue"); + fileWriteQueue.setPriority(Thread.MAX_PRIORITY); + } keyframeThumbs.clear(); frameCount = 0; @@ -1946,6 +1950,9 @@ public void startRecording(File outputFile, android.opengl.EGLContext sharedCont public void stopRecording(int send) { handler.sendMessage(handler.obtainMessage(MSG_STOP_RECORDING, send, 0)); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + }); } long prevTimestamp; @@ -1961,7 +1968,7 @@ public void frameAvailable(SurfaceTexture st, Integer cameraId, long timestampIn zeroTimeStamps++; if (zeroTimeStamps > 1) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("fix timestamp enabled"); + FileLog.d("InstantCamera fix timestamp enabled"); } timestamp = timestampInternal; } else { @@ -1997,7 +2004,7 @@ private void handleAudioFrameAvailable(AudioBufferInfo input) { if (audioFirst == -1) { if (videoFirst == -1) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("video record not yet started"); + FileLog.d("InstantCamera video record not yet started"); } return; } @@ -2009,7 +2016,7 @@ private void handleAudioFrameAvailable(AudioBufferInfo input) { audioFirst = input.offset[a]; ok = true; if (BuildVars.LOGS_ENABLED) { - FileLog.d("detected desync between audio and video " + desyncTime); + FileLog.d("InstantCamera detected desync between audio and video " + desyncTime); } break; } @@ -2018,18 +2025,18 @@ private void handleAudioFrameAvailable(AudioBufferInfo input) { audioFirst = input.offset[a]; ok = true; if (BuildVars.LOGS_ENABLED) { - FileLog.d("found first audio frame at " + a + " timestamp = " + input.offset[a]); + FileLog.d("InstantCamera found first audio frame at " + a + " timestamp = " + input.offset[a]); } break; } else { if (BuildVars.LOGS_ENABLED) { - FileLog.d("ignore first audio frame at " + a + " timestamp = " + input.offset[a]); + FileLog.d("InstantCamera ignore first audio frame at " + a + " timestamp = " + input.offset[a]); } } } if (!ok) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("first audio frame not found, removing buffers " + input.results); + FileLog.d("InstantCamera first audio frame not found, removing buffers " + input.results); } buffersToWrite.remove(input); } else { @@ -2074,9 +2081,9 @@ private void handleAudioFrameAvailable(AudioBufferInfo input) { if (!running && (input.offset[a] >= videoLast - desyncTime || totalTime >= 60_000000)) { if (BuildVars.LOGS_ENABLED) { if (totalTime >= 60_000000) { - FileLog.d("stop audio encoding because recorded time more than 60s"); + FileLog.d("InstantCamera stop audio encoding because recorded time more than 60s"); } else { - FileLog.d("stop audio encoding because of stoped video recording at " + input.offset[a] + " last video " + videoLast); + FileLog.d("InstantCamera stop audio encoding because of stoped video recording at " + input.offset[a] + " last video " + videoLast); } } @@ -2163,7 +2170,7 @@ private void handleVideoFrameAvailable(long timestampNanos, Integer cameraId) { if (videoFirst == -1) { videoFirst = timestampNanos / 1000; if (BuildVars.LOGS_ENABLED) { - FileLog.d("first video frame was at " + videoFirst); + FileLog.d("InstantCamera first video frame was at " + videoFirst); } } videoLast = timestampNanos; @@ -2172,7 +2179,7 @@ private void handleVideoFrameAvailable(long timestampNanos, Integer cameraId) { FloatBuffer vertexBuffer = InstantCameraView.this.vertexBuffer; FloatBuffer oldTextureBuffer = oldTextureTextureBuffer; if (textureBuffer == null || vertexBuffer == null) { - FileLog.d("handleVideoFrameAvailable skip frame " + textureBuffer + " " + vertexBuffer); + FileLog.d("InstantCamera handleVideoFrameAvailable skip frame " + textureBuffer + " " + vertexBuffer); return; } @@ -2272,11 +2279,13 @@ public void run() { private void handleStopRecording(final int send) { if (running) { + FileLog.d("InstantCamera handleStopRecording running=false"); sendWhenDone = send; running = false; return; } try { + FileLog.d("InstantCamera handleStopRecording drain encoders"); drainEncoder(true); } catch (Exception e) { FileLog.e(e); @@ -2301,30 +2310,40 @@ private void handleStopRecording(final int send) { FileLog.e(e); } } + if (mediaMuxer != null) { - CountDownLatch countDownLatch = new CountDownLatch(1); - fileWriteQueue.postRunnable(() -> { + if (WRITE_TO_FILE_IN_BACKGROUND) { + CountDownLatch countDownLatch = new CountDownLatch(1); + fileWriteQueue.postRunnable(() -> { + try { + mediaMuxer.finishMovie(); + } catch (Exception e) { + e.printStackTrace(); + } + countDownLatch.countDown(); + }); + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { try { mediaMuxer.finishMovie(); } catch (Exception e) { - e.printStackTrace(); + FileLog.e(e); } - countDownLatch.countDown(); - }); - try { - countDownLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); } + FileLog.d("InstantCamera handleStopRecording finish muxer"); if (writingToDifferentFile) { if (!fileToWrite.renameTo(videoFile)) { - FileLog.e("unable to rename file, try move file"); + FileLog.e("InstantCamera unable to rename file, try move file"); try { AndroidUtilities.copyFile(fileToWrite, videoFile); fileToWrite.delete(); } catch (IOException e) { FileLog.e(e); - FileLog.e("unable to move file"); + FileLog.e("InstantCamera unable to move file"); } } } @@ -2334,6 +2353,7 @@ private void handleStopRecording(final int send) { generateKeyframeThumbsQueue.recycle(); generateKeyframeThumbsQueue = null; } + FileLog.d("InstantCamera handleStopRecording send " + send); if (send != 0) { AndroidUtilities.runOnUIThread(() -> { videoEditedInfo = new VideoEditedInfo(); @@ -2486,7 +2506,7 @@ private void prepareEncoder() { audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); audioRecorder.startRecording(); if (BuildVars.LOGS_ENABLED) { - FileLog.d("initied audio record with channels " + audioRecorder.getChannelCount() + " sample rate = " + audioRecorder.getSampleRate() + " bufferSize = " + bufferSize); + FileLog.d("InstantCamera initied audio record with channels " + audioRecorder.getChannelCount() + " sample rate = " + audioRecorder.getSampleRate() + " bufferSize = " + bufferSize); } Thread thread = new Thread(recorderRunnable); thread.setPriority(Thread.MAX_PRIORITY); @@ -2796,7 +2816,6 @@ public void drainEncoder(boolean endOfStream) throws Exception { if (Build.VERSION.SDK_INT < 21) { encoderOutputBuffers = audioEncoder.getOutputBuffers(); } - boolean encoderOutputAvailable = true; while (true) { int encoderStatus = audioEncoder.dequeueOutputBuffer(audioBufferInfo, 0); if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { @@ -2844,13 +2863,17 @@ public void drainEncoder(boolean endOfStream) throws Exception { didWriteData(videoFile, availableSize, false); } }); - audioEncoder.releaseOutputBuffer(encoderStatus, false); + if (audioEncoder != null) { + audioEncoder.releaseOutputBuffer(encoderStatus, false); + } } else { long availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, audioBufferInfo, false); if (availableSize != 0 && !writingToDifferentFile) { didWriteData(videoFile, availableSize, false); } - audioEncoder.releaseOutputBuffer(encoderStatus, false); + if (audioEncoder != null) { + audioEncoder.releaseOutputBuffer(encoderStatus, false); + } } } else if (audioEncoder != null) { audioEncoder.releaseOutputBuffer(encoderStatus, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java index 5cc3b6cffe..685469bbfd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -30,6 +30,7 @@ public class PremiumLockIconView extends ImageView { StarParticlesView.Drawable starParticles; private boolean locked; private Theme.ResourcesProvider resourcesProvider; + boolean attachedToWindow; public PremiumLockIconView(Context context, int type) { this(context, type, null); @@ -165,6 +166,9 @@ public ImageReceiver getImageReceiver() { } private void updateGradient() { + if (!attachedToWindow) { + return; + } if (getMeasuredHeight() != 0 && getMeasuredWidth() != 0) { int c1 = currentColor; int c2; @@ -192,6 +196,27 @@ private void updateGradient() { } } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + attachedToWindow = true; + if (type != TYPE_REACTIONS) { + updateGradient(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + attachedToWindow = false; + if (paint != null) { + paint.setShader(null); + paint = null; + } + shader = null; + wasDrawn = false; + } + public void setWaitingImage() { waitingImage = true; wasDrawn = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index 2feca26b32..18a855176f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -2017,8 +2017,10 @@ protected void sendInternal(boolean withSound) { params = SendMessagesHelper.SendMessageParams.of(sendingText[num], key, null, replyTopMsg, null, true, null, null, null, withSound, 0, null, false); } } else { + if (frameLayout2.getTag() != null && commentTextView.length() > 0 && text[0] != null) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(SendMessagesHelper.SendMessageParams.of(text[0].toString(), key, null, replyTopMsg, null, true, null, null, null, withSound, 0, null, false)); + } params = SendMessagesHelper.SendMessageParams.of(null, key, null, replyTopMsg, null, true, null, null, null, withSound, 0, null, false); - params.caption = frameLayout2.getTag() != null && commentTextView.length() > 0 && text[0] != null ? text[0].toString() : null; params.sendingStory = storyItem; } SendMessagesHelper.getInstance(currentAccount).sendMessage(params); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java index 1e1066dde0..25799cfb7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java @@ -298,7 +298,6 @@ public void draw(@NonNull Canvas canvas) { int dt = (int) Math.min(curTime - lastDrawTime, renderDelayMs); boolean hasAnimator = false; - lastDrawTime = curTime; int left = getBounds().left, top = getBounds().top, right = getBounds().right, bottom = getBounds().bottom; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffectBitmapFactory.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffectBitmapFactory.java index fc1ac7efa7..7b6a3a4735 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffectBitmapFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffectBitmapFactory.java @@ -39,17 +39,17 @@ public static SpoilerEffectBitmapFactory getInstance() { int size; private SpoilerEffectBitmapFactory() { - int maxSize = SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? AndroidUtilities.dp(200) : AndroidUtilities.dp(150); + int maxSize = SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? AndroidUtilities.dp(150) : AndroidUtilities.dp(100); size = (int) Math.min(Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f, maxSize); - if (size < AndroidUtilities.dp(100)) { - size = AndroidUtilities.dp(100); + if (size < AndroidUtilities.dp(80)) { + size = AndroidUtilities.dp(80); } } Paint getPaint() { if (shaderBitmap == null) { - shaderBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + shaderBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ALPHA_8); shaderCanvas = new Canvas(shaderBitmap); shaderPaint = new Paint(); shaderSpoilerEffects = new ArrayList<>(10 * 10); @@ -89,10 +89,10 @@ public void checkUpdate() { dispatchQueue.postRunnable(() -> { Bitmap bitmap = bufferBitmapFinall; if (bitmap == null) { - bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ALPHA_8); } if (backgroundBitmap == null) { - backgroundBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + backgroundBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ALPHA_8); } else { backgroundBitmap.eraseColor(Color.TRANSPARENT); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java index 6f802432ab..0e79b4ff16 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java @@ -10,16 +10,18 @@ import android.graphics.Region; import android.text.Layout; import android.text.Spanned; +import android.text.StaticLayout; import android.view.MotionEvent; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.Cells.TextSelectionHelper; import java.util.ArrayList; import java.util.List; import java.util.Stack; -public class SpoilersTextView extends TextView { +public class SpoilersTextView extends TextView implements TextSelectionHelper.SimpleSelectabeleView { private SpoilersClickDetector clickDetector; protected List spoilers = new ArrayList<>(); private Stack spoilersPool = new Stack<>(); @@ -147,4 +149,9 @@ private void invalidateSpoilers() { } invalidate(); } + + @Override + public Layout getStaticTextLayout() { + return getLayout(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index f937991091..db22d390c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -704,7 +704,6 @@ public void reset() { public boolean onTouch(MotionEvent event, final RecyclerListView listView, final int height, final Object listener, ContentPreviewViewerDelegate contentPreviewViewerDelegate, Theme.ResourcesProvider resourcesProvider) { delegate = contentPreviewViewerDelegate; - this.resourcesProvider = resourcesProvider; if (delegate != null && !delegate.can()) { return false; } @@ -908,7 +907,6 @@ protected void runSmoothHaptic() { public boolean onInterceptTouchEvent(MotionEvent event, final RecyclerListView listView, final int height, ContentPreviewViewerDelegate contentPreviewViewerDelegate, Theme.ResourcesProvider resourcesProvider) { delegate = contentPreviewViewerDelegate; - this.resourcesProvider = resourcesProvider; if (delegate != null && !delegate.can()) { return false; } @@ -1299,12 +1297,24 @@ public void close() { currentQuery = null; delegate = null; isVisible = false; + resourcesProvider = null; if (unlockPremiumView != null) { unlockPremiumView.animate().alpha(0).translationY(AndroidUtilities.dp(56)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 8); } + public void clearDelegate(ContentPreviewViewerDelegate contentPreviewViewerDelegate) { + if (delegate == contentPreviewViewerDelegate) { + currentDocument = null; + currentStickerSet = null; + currentQuery = null; + delegate = null; + resourcesProvider = null; + reset(); + } + } + public void destroy() { isVisible = false; delegate = null; @@ -1494,20 +1504,10 @@ private void prepareBlurBitmap() { AndroidUtilities.makeGlobalBlurBitmap(bitmap -> { blurrBitmap = bitmap; preparingBitmap = false; + if (containerView != null) { + containerView.invalidate(); + } }, 12); -// View parentView = parentActivity.getWindow().getDecorView(); -// int w = (int) (parentView.getMeasuredWidth() / 12.0f); -// int h = (int) (parentView.getMeasuredHeight() / 12.0f); -// Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); -// Canvas canvas = new Canvas(bitmap); -// canvas.scale(1.0f / 12.0f, 1.0f / 12.0f); -// canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite)); -// parentView.draw(canvas); -// if (parentActivity instanceof LaunchActivity && ((LaunchActivity) parentActivity).getActionBarLayout().getLastFragment().getVisibleDialog() != null) { -// ((LaunchActivity) parentActivity).getActionBarLayout().getLastFragment().getVisibleDialog().getWindow().getDecorView().draw(canvas); -// } -// Utilities.stackBlurBitmap(bitmap, Math.max(10, Math.max(w, h) / 180)); -// blurrBitmap = bitmap; } public boolean showMenuFor(View view) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java index b4ffed8925..c939b27b28 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java @@ -836,14 +836,14 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { builder.append(", "); } builder.append(LocaleController.getString("AutoDownloadVideosOn", R.string.AutoDownloadVideosOn)); - builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_VIDEO)], true))); + builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_VIDEO)], true, false))); } if (files) { if (builder.length() > 0) { builder.append(", "); } builder.append(LocaleController.getString("AutoDownloadFilesOn", R.string.AutoDownloadFilesOn)); - builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT)], true))); + builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT)], true, false))); } } else { builder.append(LocaleController.getString("NoMediaAutoDownload", R.string.NoMediaAutoDownload)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 2215cedcd8..63ca8d76cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -45,6 +45,7 @@ import android.os.Bundle; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Log; import android.util.LongSparseArray; import android.util.Property; import android.util.StateSet; @@ -1925,7 +1926,7 @@ protected void onMeasure(int widthSpec, int heightSpec) { ignoreLayout = false; } } else if (pos == RecyclerView.NO_POSITION && firstLayout) { - parentPage.layoutManager.scrollToPositionWithOffset(hasHiddenArchive() ? 1 : 0, (int) scrollYOffset); + parentPage.layoutManager.scrollToPositionWithOffset(parentPage.dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() ? 1 : 0, (int) scrollYOffset); } if (!onlySelect || initialDialogsType == DIALOGS_TYPE_FORWARD) { ignoreLayout = true; @@ -3718,7 +3719,7 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi if (firstView != null) { firstView.invalidate(); } - if (viewPage.archivePullViewState == ARCHIVE_ITEM_STATE_SHOWED && usedDy == 0 && dy < 0 && isDragging && !rightSlidingDialogContainer.hasFragment() && hasStories) { + if (viewPage.archivePullViewState == ARCHIVE_ITEM_STATE_SHOWED && usedDy == 0 && dy < 0 && isDragging && !rightSlidingDialogContainer.hasFragment() && hasStories && progressToActionMode == 0) { float newOverScroll = storiesOverscroll - dy * AndroidUtilities.lerp( 0.2f, 0.5f, dialogStoriesCell.overscrollProgress()); setStoriesOvercroll(viewPage, newOverScroll); } @@ -3726,7 +3727,7 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi } int scrolled = super.scrollVerticallyBy(measuredDy, recycler, state); - if (scrolled == 0 && dy < 0 && isDragging && !rightSlidingDialogContainer.hasFragment() && hasStories) { + if (scrolled == 0 && dy < 0 && isDragging && !rightSlidingDialogContainer.hasFragment() && hasStories && progressToActionMode == 0) { float newOverScroll = storiesOverscroll - dy * AndroidUtilities.lerp(0.2f, 0.5f, dialogStoriesCell.overscrollProgress()); setStoriesOvercroll(viewPage, newOverScroll); } @@ -5359,7 +5360,7 @@ private void clearCacheHintVisible() { // } public void showSelectStatusDialog() { - if (selectAnimatedEmojiDialog != null || SharedConfig.appLocked || !dialogStoriesCell.isExpanded()) { + if (selectAnimatedEmojiDialog != null || SharedConfig.appLocked || (hasStories && !dialogStoriesCell.isExpanded())) { return; } final SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow[] popup = new SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow[1]; @@ -6389,7 +6390,9 @@ public void finishFragment() { @Override public void onResume() { super.onResume(); - dialogStoriesCell.onResume(); + if (dialogStoriesCell != null) { + dialogStoriesCell.onResume(); + } if (rightSlidingDialogContainer != null) { rightSlidingDialogContainer.onResume(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 9d5355e1a3..b3287f2f53 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -186,6 +186,7 @@ import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.PhotoPickerPhotoCell; +import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -297,6 +298,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private PhotoViewerActionBarContainer actionBarContainer; private PhotoCountView countView; public boolean closePhotoAfterSelect = true; + private TextSelectionHelper.SimpleTextSelectionHelper textSelectionHelper; private static class PhotoViewerActionBarContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -4464,6 +4466,19 @@ public int getBottomOffset(int tag) { } }; + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (textSelectionHelper.isInSelectionMode()) { + textSelectionHelper.getOverlayView(getContext()).checkCancelAction(ev); + + if (textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { + return true; + } + return true; + } + return super.dispatchTouchEvent(ev); + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -4477,6 +4492,22 @@ protected void onDetachedFromWindow() { Bulletin.removeDelegate(this); } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); + if (child == overlay) { + return false; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); + overlay.draw(canvas); + } }; containerView.setFocusable(false); @@ -6129,7 +6160,6 @@ public void setAlpha(float alpha) { return false; }); - captionLimitView = new TextView(parentActivity); captionLimitView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); captionLimitView.setTextColor(0xffEC7777); @@ -7025,6 +7055,16 @@ public void onContextClick(TLRPC.BotInlineResult result) { doneButtonFullWidth.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 6)); doneButtonFullWidth.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); + + textSelectionHelper = new TextSelectionHelper.SimpleTextSelectionHelper(null, resourcesProvider); + textSelectionHelper.useMovingOffset = false; + View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); + if (overlay != null) { + AndroidUtilities.removeFromParent(overlay); + containerView.addView(overlay); + } + textSelectionHelper.setParentView(containerView); + textSelectionHelper.setInvalidateParent(); } public void showCaptionLimitBulletin(FrameLayout view) { @@ -7388,7 +7428,7 @@ public void onAnimationCancel(Animator animation) { } private TextView createCaptionTextView() { - TextView textView = new SpoilersTextView(activityContext) { + SpoilersTextView textView = new SpoilersTextView(activityContext) { private LinkSpanDrawable pressedLink; private LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this); @@ -7398,6 +7438,11 @@ public boolean onTouchEvent(MotionEvent event) { if (getLayout() == null) { return false; } + if (textSelectionHelper != null && getStaticTextLayout() != null) { + textSelectionHelper.setSelectabeleView(this); + textSelectionHelper.update(getPaddingLeft(), getPaddingTop()); + textSelectionHelper.onTouchEvent(event); + } boolean linkResult = false; if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) { int x = (int) (event.getX() - getPaddingLeft()); @@ -7452,6 +7497,7 @@ public boolean onTouchEvent(MotionEvent event) { return bottomTouchEnabled && b; } + @Override public void setPressed(boolean pressed) { final boolean needsRefresh = pressed != isPressed(); @@ -7465,6 +7511,15 @@ public void setPressed(boolean pressed) { @Override protected void onDraw(Canvas canvas) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + if (textSelectionHelper != null && getStaticTextLayout() != null && textSelectionHelper.isCurrent(this)) { + textSelectionHelper.draw(canvas); + } + canvas.restore(); + } + canvas.save(); canvas.translate(getPaddingLeft(), 0); if (links.draw(canvas)) { @@ -7504,6 +7559,7 @@ protected void dispatchDraw(Canvas canvas) { canvas.restore(); } }; + ViewHelper.setPadding(textView, 16, 8, 16, 8); textView.setLinkTextColor(0xff79c4fc); textView.setTextColor(0xffffffff); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SaveToGallerySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SaveToGallerySettingsActivity.java index 29df80b3b7..72c901891e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SaveToGallerySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SaveToGallerySettingsActivity.java @@ -399,7 +399,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int SelectableAnimatedTextView lowerTextView = new SelectableAnimatedTextView(getContext()); lowerTextView.setTextSize(AndroidUtilities.dp(13)); - lowerTextView.setText(AndroidUtilities.formatFileSize(1024 * 512, true)); + lowerTextView.setText(AndroidUtilities.formatFileSize(1024 * 512, true, false)); textContainer.addView(lowerTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); SelectableAnimatedTextView midTextView = new SelectableAnimatedTextView(getContext()); @@ -409,7 +409,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int SelectableAnimatedTextView topTextView = new SelectableAnimatedTextView(getContext()); topTextView.setTextSize(AndroidUtilities.dp(13)); - topTextView.setText(AndroidUtilities.formatFileSize(SaveToGallerySettingsHelper.MAX_VIDEO_LIMIT, true)); + topTextView.setText(AndroidUtilities.formatFileSize(SaveToGallerySettingsHelper.MAX_VIDEO_LIMIT, true, false)); textContainer.addView(topTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM)); @@ -450,7 +450,7 @@ public void onSeekBarDrag(boolean stop, float progress) { } else { midTextView.setText( LocaleController.formatString("UpToFileSize", R.string.UpToFileSize, - AndroidUtilities.formatFileSize(value, true) + AndroidUtilities.formatFileSize(value, true, false) ), false); lowerTextView.setSelectedInternal(false, animated); midTextView.setSelectedInternal(true, animated); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index f2be158326..8cea04c7bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -212,7 +212,7 @@ public boolean onFragmentCreate() { if (recentPostsAll.size() > 0) { int lastPostId = recentPostsAll.get(0).counters.msg_id; int count = recentPostsAll.size(); - getMessagesStorage().getMessages(-chat.id, 0, false, count, lastPostId, 0, 0, classGuid, 0, false, 0, 0, true, false); + getMessagesStorage().getMessages(-chat.id, 0, false, count, lastPostId, 0, 0, classGuid, 0, false, 0, 0, true, false, null); } AndroidUtilities.runOnUIThread(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java index 951ba834e0..593170db34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java @@ -138,6 +138,7 @@ public DarkThemeResourceProvider() { sparseIntArray.put(Theme.key_chat_outBubbleGradient1, 0); sparseIntArray.put(Theme.key_chat_outBubbleGradient2, 0); sparseIntArray.put(Theme.key_chat_outBubbleGradient3, 0); + sparseIntArray.put(Theme.key_chat_textSelectBackground, ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.6f)); appendColors(); dividerPaint.setColor(getColor(Theme.key_divider)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java index a02920bbc5..b981564879 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -14,9 +14,12 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Layout; +import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.ClickableSpan; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; @@ -58,6 +61,7 @@ import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.recorder.HintView2; import org.telegram.ui.Stories.recorder.StoryRecorder; @@ -1273,6 +1277,7 @@ public void onAnimationEnd(Animator animation) { params.progressToArc = getArcProgress(cx, radius); params.isLast = isLast; params.isFirst = isFirst; + params.crossfadeToDialog = 0; StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasSelfStories(), params); // avatarImage.draw(canvas); } @@ -1292,6 +1297,12 @@ public void onAnimationEnd(Animator animation) { params.progressToArc = getArcProgress(cx, radius); params.isLast = isLast; params.isFirst = isFirst; + if (crossfadeToDialog) { + params.crossfadeToDialog = crossfadeToDialogId; + params.crossfadeToDialogProgress = progressToCollapsed2; + } else { + params.crossfadeToDialog = 0; + } StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasStories(dialogId), params); // avatarImage.draw(canvas); } @@ -1475,6 +1486,7 @@ public void setProgressToCollapsed(float progressToCollapsed, float progressToCo public void setCrossfadeTo(long dialogId) { if (crossfadeToDialogId != dialogId) { + this.crossfadeToDialogId = dialogId; crossfadeToDialog = dialogId != -1; if (crossfadeToDialog) { TLObject object; @@ -1604,12 +1616,18 @@ private HintView2 makePremiumHint() { .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_CENTER) .setJoint(0, 37 - 8); - CharSequence text = AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint").replace('\n', ' '), Theme.key_undo_cancelColor, 0, () -> { + Spannable text = AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint").replace('\n', ' '), Theme.key_undo_cancelColor, 0, () -> { if (premiumHint != null) { premiumHint.hide(); } fragment.presentFragment(new PremiumPreviewFragment("stories")); }); + ClickableSpan[] spans = text.getSpans(0, text.length(), ClickableSpan.class); + if (spans != null && spans.length >= 1) { + int start = text.getSpanStart(spans[0]); + int end = text.getSpanEnd(spans[0]); + text.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } premiumHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, premiumHint.getTextPaint())); premiumHint.setText(text); premiumHint.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(24), AndroidUtilities.dp(8), 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java index 93e4859ad5..c4ac21db8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -92,6 +92,7 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; @@ -464,11 +465,7 @@ protected void dispatchDraw(Canvas canvas) { canvas.drawPaint(sharedResources.gradientBackgroundPaint); } if (progressToFullBlackout < 1f) { - if (progressToDismiss != 0) { - canvas.saveLayerAlpha(0, gradientTop, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG); - } else { - canvas.save(); - } + canvas.save(); sharedResources.gradientBackgroundPaint.setColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.506f * (1f - progressToFullBlackout) * hideCaptionAlpha))); sharedResources.bottomOverlayGradient.setAlpha((int) (255 * (1f - progressToFullBlackout) * hideCaptionAlpha)); sharedResources.bottomOverlayGradient.setBounds(0, gradientTop, getMeasuredWidth(), gradientBottom); @@ -777,15 +774,16 @@ public void onEmojiClick(AnimatedEmojiSpan span) { bulletin.show(true); } }; - storyCaptionView.captionTextview.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (storyCaptionView.expanded) { + storyCaptionView.captionTextview.setOnClickListener(v -> { + if (storyCaptionView.expanded) { + if (!storyCaptionView.textSelectionHelper.isInSelectionMode()) { storyCaptionView.collapse(); } else { - checkBlackoutMode = true; - storyCaptionView.expand(); + storyCaptionView.checkCancelTextSelection(); } + } else { + checkBlackoutMode = true; + storyCaptionView.expand(); } }); @@ -1226,6 +1224,19 @@ protected void onDismissed() { muteIconContainer.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(20), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 100))); optionsIconView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(20), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 100))); shareButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(20), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 100))); + + View overlay = storyCaptionView.textSelectionHelper.getOverlayView(context); + if (overlay != null) { + AndroidUtilities.removeFromParent(overlay); + addView(overlay); + } + storyCaptionView.textSelectionHelper.setCallback(new TextSelectionHelper.Callback() { + @Override + public void onStateChanged(boolean isSelected) { + delegate.setIsInSelectionMode(storyCaptionView.textSelectionHelper.isInSelectionMode()); + } + }); + storyCaptionView.textSelectionHelper.setParentView(this); } private ArrayList getAnimatedEmojiSets(StoryItemHolder storyHolder) { @@ -3044,6 +3055,10 @@ public int getSelectedPosition() { } public boolean closeKeyboardOrEmoji() { + if (storyCaptionView.textSelectionHelper.isInSelectionMode()) { + storyCaptionView.textSelectionHelper.clear(false); + return true; + } if (privacyHint != null) { privacyHint.hide(); } @@ -3149,6 +3164,7 @@ public void setActive(long t, boolean active) { //storyViewer.allowScreenshots(allowScreenshots); } else { + cancelTextSelection(); muteIconView.clearAnimationDrawable(); viewsThumbImageReceiver = null; isLongPressed = false; @@ -3196,6 +3212,7 @@ public void reset() { progressToHideInterface.set(0, false); viewsThumbImageReceiver = null; messageSent = false; + cancelTextSelection(); } public void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -3377,6 +3394,26 @@ public void showNoSoundHint() { muteIconContainer.callOnClick(); } + public boolean checkTextSelectionEvent(MotionEvent ev) { + if (storyCaptionView.textSelectionHelper.isInSelectionMode()) { + float xOffset = getX(); + float yOffset = getY() + ((View) getParent()).getY(); + ev.offsetLocation(-xOffset, -yOffset); + if (storyCaptionView.textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { + return true; + } else { + ev.offsetLocation(xOffset, yOffset); + } + } + return false; + } + + public void cancelTextSelection() { + if (storyCaptionView.textSelectionHelper.isInSelectionMode()) { + storyCaptionView.textSelectionHelper.clear(); + } + } + public static class PeerHeaderView extends FrameLayout { public BackupImageView backupImageView; @@ -3601,6 +3638,8 @@ public interface Delegate { void setIsHintVisible(boolean visible); void setIsSwiping(boolean swiping); + + void setIsInSelectionMode(boolean selectionMode); } public class StoryItemHolder { @@ -4006,6 +4045,12 @@ private void updateViewOffsets() { if (progressToHideInterface.get() != prevToHideProgress) { storyContainer.invalidate(); } + if (progressToDismissLocal != 0) { + //fix jittering caption shadow + storyContainer.setLayerType(LAYER_TYPE_HARDWARE, null); + } else { + storyContainer.setLayerType(LAYER_TYPE_NONE, null); + } prevToHideProgress = progressToHideInterface.get(); progressToDismiss = progressToDismissLocal; progressToKeyboard = progressToKeyboardLocal; @@ -4014,6 +4059,7 @@ private void updateViewOffsets() { return; } + if (reactionsContainerLayout != null) { reactionsContainerLayout.setVisibility(progressToKeyboard > 0 ? View.VISIBLE : View.GONE); } @@ -4031,7 +4077,7 @@ private void updateViewOffsets() { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); - if (child.getVisibility() != View.VISIBLE || child == selfView || child.getTag(R.id.parent_tag) != null) { + if (child.getVisibility() != View.VISIBLE || child == selfView || child.getTag(R.id.parent_tag) != null || child == storyCaptionView.textSelectionHelper.getOverlayView(getContext())) { if (child == selfView) { if (BIG_SCREEN) { child.setAlpha((1f - progressToDismiss) * hideInterfaceAlpha * (1f - outT)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java index bc59e11929..a5d8290d59 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -70,7 +70,6 @@ public SelfStoryViewsPage(StoryViewer storyViewer, @NonNull Context context) { titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); titleView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(6), AndroidUtilities.dp(21), AndroidUtilities.dp(8)); - addView(titleView); recyclerListView = new RecyclerListView(context) { @Override @@ -109,15 +108,18 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { View shadowView2 = new View(getContext()); shadowView2.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); - addView(shadowView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 8, 0, 0, TOP_PADDING - 16, 0, 0)); + addView(shadowView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 10, 0, 0, TOP_PADDING - 17, 0, 0)); + addView(titleView); } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child == recyclerListView) { + canvas.save(); canvas.clipRect(0, AndroidUtilities.dp(TOP_PADDING), getMeasuredWidth(), getMeasuredHeight()); super.drawChild(canvas, child, drawingTime); + canvas.restore(); return true; } return super.drawChild(canvas, child, drawingTime); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java index db0e06e570..e2d250eee8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java @@ -216,9 +216,11 @@ public void setOffset(float selfStoriesViewsOffset) { float alpha = Utilities.clamp(progressToOpen / 0.5f, 1f, 0); // selfStoriesPreviewView.setAlpha(alpha); - PeerStoriesView currentView = storyViewer.getCurrentPeerView(); + final PeerStoriesView currentView = storyViewer.getCurrentPeerView(); if (oldProgressToOpen == 1f && progressToOpen != 1f) { - currentView.selectPosition(selfStoriesPreviewView.getClosestPosition()); + if (currentView != null) { + currentView.selectPosition(selfStoriesPreviewView.getClosestPosition()); + } selfStoriesPreviewView.abortScroll(); } if (currentView != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java index 9b8be57e44..a18df5b671 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -13,6 +13,7 @@ import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.DialogCell; +import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.ReactedUserHolderView; import org.telegram.ui.Cells.SharedPhotoVideoCell2; import org.telegram.ui.Cells.UserCell; @@ -178,6 +179,16 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto updateClip(holder); return true; } + } else if (child instanceof ProfileSearchCell) { + ProfileSearchCell cell = (ProfileSearchCell) child; + if (cell.getDialogId() == dialogId) { + holder.view = cell; + holder.params = cell.avatarStoryParams; + holder.avatarImage = cell.avatarImage; + holder.clipParent = (View) cell.getParent(); + updateClip(holder); + return true; + } } } return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java index 07550cdb99..dc39fb335f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java @@ -33,6 +33,7 @@ import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedTextView; @@ -40,6 +41,7 @@ import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.GradientTools; +import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.LaunchActivity; import java.util.Collections; @@ -247,7 +249,13 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv if (params.drawSegments) { checkGrayPaint(); checkStoryCellGrayPaint(params.isArchive); - int globalState = storiesController.getUnreadState(dialogId); + int globalState; + if (params.crossfadeToDialog != 0) { + globalState = storiesController.getUnreadState(params.crossfadeToDialog); + } else { + globalState = storiesController.getUnreadState(dialogId); + } + params.globalState = globalState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD; TLRPC.TL_userStories userStories = storiesController.getStories(params.dialogId); int storiesCount; @@ -256,6 +264,16 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv } else { storiesCount = userStories == null || userStories.stories.size() == 1 ? 1 : userStories.stories.size(); } + Paint globalPaint; + if (globalState == StoriesController.STATE_UNREAD_CLOSE_FRIEND) { + getCloseFriendsPaint(avatarImage); + globalPaint = closeFriendsGradientTools.paint; + } else if (globalState == StoriesController.STATE_UNREAD) { + getActiveCirclePaint(avatarImage, params.isStoryCell); + globalPaint = storiesGradientTools[params.isStoryCell ? 1 : 0].paint; + } else { + globalPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint; + } if (storiesCount == 1) { Paint localPaint = paint; if (storiesController.hasUnreadStories(dialogId)) { @@ -267,6 +285,17 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv startAngle = 90; endAngle = 270; drawSegment(canvas, rectTmp, localPaint, startAngle, endAngle, params); + + if (params.progressToSegments != 1 && localPaint != globalPaint) { + globalPaint.setAlpha((int) (255 * (1f - params.progressToSegments))); + startAngle = -90; + endAngle = 90; + drawSegment(canvas, rectTmp, globalPaint, startAngle, endAngle, params); + startAngle = 90; + endAngle = 270; + drawSegment(canvas, rectTmp, globalPaint, startAngle, endAngle, params); + globalPaint.setAlpha(255); + } // canvas.drawCircle(rectTmp.centerX(), rectTmp.centerY(), rectTmp.width() / 2f, localPaint); } else { float step = 360 / (float) storiesCount; @@ -275,16 +304,7 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv if (gapLen > step) { gapLen = 0;//step * 0.4f; } - Paint globalPaint; - if (globalState == StoriesController.STATE_UNREAD_CLOSE_FRIEND) { - getCloseFriendsPaint(avatarImage); - globalPaint = closeFriendsGradientTools.paint; - } else if (globalState == StoriesController.STATE_UNREAD) { - getActiveCirclePaint(avatarImage, params.isStoryCell); - globalPaint = storiesGradientTools[params.isStoryCell ? 1 : 0].paint; - } else { - globalPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint; - } + int maxUnread = params.drawHiddenStoriesAsSegments ? 0 : Math.max(userStories.max_read_id, storiesController.dialogIdToMaxReadId.get(dialogId, 0)); for (int i = 0; i < storiesCount; i++) { @@ -751,6 +771,8 @@ public static class AvatarStoryParams { public int unreadState; public int animateFromUnreadState; public boolean drawHiddenStoriesAsSegments; + public long crossfadeToDialog; + public float crossfadeToDialogProgress; private long dialogId; public int currentState; @@ -792,8 +814,10 @@ private void updateProgressParams() { float startX, startY; Runnable longPressRunnable; + public View child; public boolean checkOnTouchEvent(MotionEvent event, View view) { + child = view; StoriesController storiesController = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController(); if (event.getAction() == MotionEvent.ACTION_DOWN && originalAvatarRect.contains(event.getX(), event.getY())) { TLRPC.User user = MessagesController.getInstance(UserConfig.selectedAccount).getUser(dialogId); @@ -891,6 +915,11 @@ private void processOpenStory(View view) { } public void openStory(long dialogId, Runnable onDone) { + BaseFragment fragment = LaunchActivity.getLastFragment(); + if (fragment != null && child != null) { + fragment.getOrCreateStoryViewer().doOnAnimationReady(onDone); + fragment.getOrCreateStoryViewer().open(fragment.getContext(), dialogId, StoriesListPlaceProvider.of((RecyclerListView) child.getParent())); + } } public float getScale() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java index 8a197f7e62..b66ac70ac4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java @@ -9,6 +9,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; @@ -168,7 +169,7 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse @Override public void onPageSelected(int position) { - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView == null) { return; } @@ -222,6 +223,7 @@ public boolean canScroll(float dx) { return true; } + @Nullable public PeerStoriesView getCurrentPeerView() { for (int i = 0; i < getChildCount(); i++) { if ((Integer) getChildAt(i).getTag() == getCurrentItem()) { @@ -264,7 +266,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (updateDelegate) { updateDelegate = false; - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView != null) { delegate.onPeerSelected(peerStoriesView.getCurrentPeer(), peerStoriesView.getSelectedPosition()); } @@ -343,7 +345,7 @@ public void onNextIdle(Runnable runnable) { public void setKeyboardHeight(int realKeyboardHeight) { if (keyboardHeight != realKeyboardHeight) { keyboardHeight = realKeyboardHeight; - View view = getCurrentPeerView(); + final View view = getCurrentPeerView(); if (view != null) { view.requestLayout(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java index 3fd7df309b..67392a8428 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java @@ -49,6 +49,7 @@ import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -72,6 +73,8 @@ public class StoryCaptionView extends NestedScrollView { private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + TextSelectionHelper.SimpleTextSelectionHelper textSelectionHelper; + private final SpringAnimation springAnimation; public StoryCaptionTextView captionTextview; @@ -80,6 +83,9 @@ public class StoryCaptionView extends NestedScrollView { private float velocitySign; private float velocityY; + private float lastMotionX; + private float lastMotionY; + private Method abortAnimatedScrollMethod; private OverScroller scroller; @@ -109,11 +115,8 @@ public StoryCaptionView(@NonNull Context context, Theme.ResourcesProvider resour NotificationCenter.listenEmojiLoading(this); captionTextview = new StoryCaptionTextView(getContext(), resourcesProvider); - //captionTextview.setTextIsSelectable(true); - - //captionTextview.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), AndroidUtilities.dp(8)); - - + textSelectionHelper = new TextSelectionHelper.SimpleTextSelectionHelper(captionTextview, resourcesProvider); + textSelectionHelper.useMovingOffset = false; captionContainer.addView(captionTextview, LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT); addView(captionContainer, new ViewGroup.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -322,6 +325,7 @@ public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] off } captionTextview.setTranslationY(overScrollY); + textSelectionHelper.invalidate(); return true; } @@ -359,6 +363,7 @@ public void dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsume } } } + textSelectionHelper.invalidate(); } private void startSpringAnimationIfNotRunning(float velocityY) { @@ -466,6 +471,7 @@ public void invalidate() { if (getParent() != null) { ((View) getParent()).invalidate(); } + textSelectionHelper.invalidate(); } public float getProgressToBlackout() { @@ -539,7 +545,13 @@ public boolean hasScroll() { return captionContainer.getBottom() - getMeasuredHeight() > 0; } - public class StoryCaptionTextView extends View { + public void checkCancelTextSelection() { + if (textSelectionHelper.isInSelectionMode()) { + textSelectionHelper.getOverlayView(getContext()).checkCancel(lastMotionX, lastMotionY, false); + } + } + + public class StoryCaptionTextView extends View implements TextSelectionHelper.SelectableView, TextSelectionHelper.SimpleSelectabeleView { private final PorterDuffColorFilter emojiColorFilter; private LinkSpanDrawable pressedLink; @@ -561,7 +573,6 @@ public class StoryCaptionTextView extends View { int textHeight; float textX; float textY; - boolean expanded = false; float progressToExpand; float showMoreY; float showMoreX; @@ -621,7 +632,11 @@ public void setText(CharSequence text) { // invalidateSpoilers(); this.text = text; sizeCached = 0; + if (getMeasuredWidth() > 0) { + createLayout(getMeasuredWidth()); + } requestLayout(); + invalidate(); } @SuppressLint("DrawAllocation") @@ -632,63 +647,67 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { verticalPadding = AndroidUtilities.dp(8); if (sizeCached != size) { sizeCached = size; - int width = MeasureSpec.getSize(widthMeasureSpec) - horizontalPadding * 2; - fullLayout = makeTextLayout(textPaint, text, width); - textHeight = fullLayout.getHeight(); - textX = horizontalPadding; - textY = verticalPadding; - float space = textPaint.measureText(" "); - if (fullLayout.getLineCount() > 3) { - String showMoreText = LocaleController.getString("ShowMore", R.string.ShowMore); - showMore = makeTextLayout(showMorePaint, showMoreText, width); - - float collapsedY = fullLayout.getLineTop(2) + fullLayout.getTopPadding(); - showMoreY = textY + collapsedY - AndroidUtilities.dpf2(0.3f); - showMoreX = MeasureSpec.getSize(widthMeasureSpec) - horizontalPadding - showMorePaint.measureText(showMoreText); - firstLayout = makeTextLayout(textPaint, text.subSequence(0, fullLayout.getLineEnd(2)), width); - spoilersPool.addAll(spoilers); - spoilers.clear(); - SpoilerEffect.addSpoilers(this, fullLayout, spoilersPool, spoilers); - - float x = fullLayout.getLineRight(2) + space; - if (nextLinesLayouts != null) { - for (int i = 0; i < nextLinesLayouts.length; i++) { - if (nextLinesLayouts[i] == null) { - continue; - } - AnimatedEmojiSpan.release(this, nextLinesLayouts[i].layoutEmoji); + createLayout(MeasureSpec.getSize(widthMeasureSpec)); + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(verticalPadding * 2 + textHeight, MeasureSpec.EXACTLY)); + } + + private void createLayout(int measuredWidth) { + int width = measuredWidth - horizontalPadding * 2; + fullLayout = makeTextLayout(textPaint, text, width); + textHeight = fullLayout.getHeight(); + textX = horizontalPadding; + textY = verticalPadding; + float space = textPaint.measureText(" "); + if (fullLayout.getLineCount() > 3) { + String showMoreText = LocaleController.getString("ShowMore", R.string.ShowMore); + showMore = makeTextLayout(showMorePaint, showMoreText, width); + + float collapsedY = fullLayout.getLineTop(2) + fullLayout.getTopPadding(); + showMoreY = textY + collapsedY - AndroidUtilities.dpf2(0.3f); + showMoreX = width - horizontalPadding - showMorePaint.measureText(showMoreText); + firstLayout = makeTextLayout(textPaint, text.subSequence(0, fullLayout.getLineEnd(2)), width); + spoilersPool.addAll(spoilers); + spoilers.clear(); + SpoilerEffect.addSpoilers(this, fullLayout, spoilersPool, spoilers); + + float x = fullLayout.getLineRight(2) + space; + if (nextLinesLayouts != null) { + for (int i = 0; i < nextLinesLayouts.length; i++) { + if (nextLinesLayouts[i] == null) { + continue; } + AnimatedEmojiSpan.release(this, nextLinesLayouts[i].layoutEmoji); } - nextLinesLayouts = new LineInfo[fullLayout.getLineCount() - 3]; - - if (spoilers.isEmpty()) { - for (int line = 3; line < fullLayout.getLineCount(); ++line) { - int s = fullLayout.getLineStart(line), e = fullLayout.getLineEnd(line); - final StaticLayout layout = makeTextLayout(textPaint, text.subSequence(Math.min(s, e), Math.max(s, e)), width); - LineInfo lineInfo = new LineInfo(); - nextLinesLayouts[line - 3] = lineInfo; - lineInfo.staticLayout = layout; - lineInfo.finalX = fullLayout.getLineLeft(line); - lineInfo.finalY = fullLayout.getLineTop(line) + fullLayout.getTopPadding(); - if (x < showMoreX - AndroidUtilities.dp(16)) { - lineInfo.collapsedY = collapsedY; - lineInfo.collapsedX = x; - x += layout.getLineRight(0) + space; - } else { - lineInfo.collapsedY = lineInfo.finalY; - lineInfo.collapsedX = lineInfo.finalX; - } + } + nextLinesLayouts = new LineInfo[fullLayout.getLineCount() - 3]; + + if (spoilers.isEmpty()) { + for (int line = 3; line < fullLayout.getLineCount(); ++line) { + int s = fullLayout.getLineStart(line), e = fullLayout.getLineEnd(line); + final StaticLayout layout = makeTextLayout(textPaint, text.subSequence(Math.min(s, e), Math.max(s, e)), width); + LineInfo lineInfo = new LineInfo(); + nextLinesLayouts[line - 3] = lineInfo; + lineInfo.staticLayout = layout; + lineInfo.finalX = fullLayout.getLineLeft(line); + lineInfo.finalY = fullLayout.getLineTop(line) + fullLayout.getTopPadding(); + if (x < showMoreX - AndroidUtilities.dp(16)) { + lineInfo.collapsedY = collapsedY; + lineInfo.collapsedX = x; + x += layout.getLineRight(0) + space; + } else { + lineInfo.collapsedY = lineInfo.finalY; + lineInfo.collapsedX = lineInfo.finalX; } } - } else { - showMore = null; - firstLayout = null; - spoilersPool.addAll(spoilers); - spoilers.clear(); - SpoilerEffect.addSpoilers(this, fullLayout, spoilersPool, spoilers); } + } else { + showMore = null; + firstLayout = null; + spoilersPool.addAll(spoilers); + spoilers.clear(); + SpoilerEffect.addSpoilers(this, fullLayout, spoilersPool, spoilers); } - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(verticalPadding * 2 + textHeight, MeasureSpec.EXACTLY)); } @Override @@ -710,12 +729,21 @@ protected void onDraw(Canvas canvas) { if (fullLayout != null) { canvas.save(); canvas.translate(textX, textY); + if (textSelectionHelper.isInSelectionMode()) { + textSelectionHelper.draw(canvas); + } drawLayout(fullLayout, canvas); fullLayoutEmoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, fullLayoutEmoji, fullLayout); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, fullLayout, fullLayoutEmoji, 0, spoilers, 0, 0, 0, 1f, emojiColorFilter); canvas.restore(); } } else { + if (textSelectionHelper.isInSelectionMode()) { + canvas.save(); + canvas.translate(textX, textY); + textSelectionHelper.draw(canvas); + canvas.restore(); + } if (firstLayout != null) { canvas.save(); canvas.translate(textX, textY); @@ -793,6 +821,16 @@ public Paint getPaint() { return textPaint; } + @Override + public CharSequence getText() { + return text; + } + + @Override + public StaticLayout getStaticTextLayout() { + return fullLayout; + } + public class LineInfo { private AnimatedEmojiSpan.EmojiGroupedSpans layoutEmoji; StaticLayout staticLayout; @@ -926,6 +964,8 @@ public void setTranslationY(float translationY) { @Override public boolean dispatchTouchEvent(MotionEvent event) { boolean allowIntercept = true; + lastMotionX = event.getX(); + lastMotionY = event.getY(); if (showMore != null) { AndroidUtilities.rectTmp.set(showMoreX , showMoreY, showMoreX + showMore.getWidth(), showMoreY + showMore.getHeight()); if (AndroidUtilities.rectTmp.contains(event.getX(), event.getY())) { @@ -933,6 +973,10 @@ public boolean dispatchTouchEvent(MotionEvent event) { } } if (allowIntercept && allowClickSpoilers && clickDetector.onTouchEvent(event)) return true; +// if (allowIntercept && (expanded || firstLayout == null)) { +// textSelectionHelper.update(textX, textY); +// textSelectionHelper.onTouchEvent(event); +// } return super.dispatchTouchEvent(event); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index 6d39b01d2a..62fe0795f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -22,7 +22,6 @@ import android.media.AudioManager; import android.net.Uri; import android.os.Build; -import android.util.Log; import android.util.SparseArray; import android.view.GestureDetector; import android.view.Gravity; @@ -38,6 +37,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import androidx.core.math.MathUtils; import androidx.viewpager.widget.ViewPager; @@ -74,7 +74,6 @@ import java.util.ArrayList; import java.util.Objects; -import java.util.TreeSet; public class StoryViewer { @@ -203,6 +202,7 @@ public class StoryViewer { private boolean flingCalled; private boolean invalidateOutRect; private boolean isHintVisible; + private boolean isInTextSelectionMode; private boolean isOverlayVisible; Bitmap playerStubBitmap; public Paint playerStubPaint; @@ -374,7 +374,7 @@ public boolean onSingleTapUp(@NonNull MotionEvent e) { return false; } if (allowIntercept && peerView != null) { - if (keyboardVisible || isCaption || isCaptionPartVisible || isHintVisible) { + if (keyboardVisible || isCaption || isCaptionPartVisible || isHintVisible || isInTextSelectionMode) { closeKeyboardOrEmoji(); } else { boolean forward = e.getX() > containerView.getMeasuredWidth() * 0.33f; @@ -758,6 +758,10 @@ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean swipeToReplyCancelled = false; + PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null && peerStoriesView.checkTextSelectionEvent(ev)) { + return true; + } if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { inSwipeToDissmissMode = false; AndroidUtilities.cancelRunOnUIThread(longPressRunnable); @@ -787,7 +791,6 @@ public void onAnimationEnd(Animator animation) { } if (ev.getAction() == MotionEvent.ACTION_DOWN) { swipeToReplyWaitingKeyboard = false; - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { peerStoriesView.onActionDown(ev); } @@ -812,14 +815,11 @@ public void onAnimationEnd(Animator animation) { override = true; } } - if (selfStoriesViewsOffset == 0 && !inSwipeToDissmissMode && !isCaption && storiesViewPager.currentState != ViewPager.SCROLL_STATE_DRAGGING) { - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); - if (peerStoriesView != null) { - AndroidUtilities.getViewPositionInParent(peerStoriesView.storyContainer, this, pointPosition); - ev.offsetLocation(-pointPosition[0], -pointPosition[1]); - storiesViewPager.getCurrentPeerView().checkPinchToZoom(ev); - ev.offsetLocation(pointPosition[0], pointPosition[1]); - } + if (peerStoriesView != null && selfStoriesViewsOffset == 0 && !inSwipeToDissmissMode && !isCaption && storiesViewPager.currentState != ViewPager.SCROLL_STATE_DRAGGING) { + AndroidUtilities.getViewPositionInParent(peerStoriesView.storyContainer, this, pointPosition); + ev.offsetLocation(-pointPosition[0], -pointPosition[1]); + storiesViewPager.getCurrentPeerView().checkPinchToZoom(ev); + ev.offsetLocation(pointPosition[0], pointPosition[1]); } if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { lastX.clear(); @@ -859,7 +859,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { delayedTapRunnable = () -> setInTouchMode(true); AndroidUtilities.runOnUIThread(delayedTapRunnable, 150); } - if (allowIntercept && !keyboardVisible) { + if (allowIntercept && !keyboardVisible && !isInTextSelectionMode) { AndroidUtilities.runOnUIThread(longPressRunnable, 400); } } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { @@ -869,6 +869,9 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { if (dy > dx && dy > AndroidUtilities.touchSlop * 2) { inSwipeToDissmissMode = true; PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); + if (peerView != null) { + peerView.cancelTextSelection(); + } allowSwipeToReply = !peerView.isSelf; allowSelfStoriesView = peerView.isSelf && !peerView.unsupported && peerView.currentStory.storyItem != null; if (allowSelfStoriesView) { @@ -1313,6 +1316,12 @@ public void setIsSwiping(boolean swiping) { updatePlayingMode(); } + @Override + public void setIsInSelectionMode(boolean selectionMode) { + StoryViewer.this.isInTextSelectionMode = selectionMode; + updatePlayingMode(); + } + @Override public int getKeyboardHeight() { return realKeyboardHeight; @@ -1452,10 +1461,11 @@ public WindowInsets onApplyWindowInsets(@NonNull View v, @NonNull WindowInsets i } private void showKeyboard() { - storiesViewPager.getCurrentPeerView().showKeyboard(); - AndroidUtilities.runOnUIThread(() -> { - cancelSwipeToReply(); - }, 200); + PeerStoriesView currentPeerView = storiesViewPager.getCurrentPeerView(); + if (currentPeerView != null) { + currentPeerView.showKeyboard(); + } + AndroidUtilities.runOnUIThread(this::cancelSwipeToReply, 200); } ValueAnimator swipeToViewsAnimator; @@ -1469,7 +1479,10 @@ public void cancelSwipeToViews(boolean open) { swipeToViewsAnimator = ValueAnimator.ofFloat(selfStoriesViewsOffset, open ? selfStoryViewsView.maxSelfStoriesViewsOffset : 0); swipeToViewsAnimator.addUpdateListener(animation -> { selfStoriesViewsOffset = (float) animation.getAnimatedValue(); - storiesViewPager.getCurrentPeerView().invalidate(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.invalidate(); + } containerView.invalidate(); }); swipeToViewsAnimator.addListener(new AnimatorListenerAdapter() { @@ -1477,7 +1490,10 @@ public void cancelSwipeToViews(boolean open) { public void onAnimationEnd(Animator animation) { locker.unlock(); selfStoriesViewsOffset = open ? selfStoryViewsView.maxSelfStoriesViewsOffset : 0; - storiesViewPager.getCurrentPeerView().invalidate(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.invalidate(); + } containerView.invalidate(); swipeToViewsAnimator = null; } @@ -1499,7 +1515,9 @@ private void checkSelfStoriesView() { containerView.addView(selfStoryViewsView, 0); } PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); - selfStoryViewsView.setItems(peerStoriesView.getStoryItems(), peerStoriesView.getSelectedPosition()); + if (peerStoriesView != null) { + selfStoryViewsView.setItems(peerStoriesView.getStoryItems(), peerStoriesView.getSelectedPosition()); + } } public void showDialog(Dialog dialog) { @@ -1528,7 +1546,10 @@ public void cancelSwipeToReply() { swipeToReplyOffset = (float) animation.getAnimatedValue(); int maxOffset = AndroidUtilities.dp(200); swipeToReplyProgress = Utilities.clamp(swipeToReplyOffset / maxOffset, 1f, 0); - storiesViewPager.getCurrentPeerView().invalidate(); + PeerStoriesView peerView = storiesViewPager == null ? null : storiesViewPager.getCurrentPeerView(); + if (peerView != null) { + peerView.invalidate(); + } }); swipeToReplyBackAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -1536,7 +1557,10 @@ public void onAnimationEnd(Animator animation) { swipeToReplyBackAnimator = null; swipeToReplyOffset = 0; swipeToReplyProgress = 0; - storiesViewPager.getCurrentPeerView().invalidate(); + PeerStoriesView peerView = storiesViewPager == null ? null : storiesViewPager.getCurrentPeerView(); + if (peerView != null) { + peerView.invalidate(); + } } }); swipeToReplyBackAnimator.setDuration(AdjustPanLayoutHelper.keyboardDuration); @@ -1564,6 +1588,7 @@ public boolean getStoryRect(RectF rectF) { return true; } + @Nullable public PeerStoriesView getCurrentPeerView() { if (storiesViewPager == null) { return null; @@ -1604,8 +1629,10 @@ public void toggleSilentMode() { for (int i = 0; i < preparedPlayers.size(); i++) { preparedPlayers.get(i).setAudioEnabled(!isInSilentMode, true); } - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); - peerStoriesView.sharedResources.setIconMuted(!soundEnabled(), true); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.sharedResources.setIconMuted(!soundEnabled(), true); + } } private void checkInSilentMode() { @@ -1626,7 +1653,7 @@ private void layoutAndFindView() { transitionViewHolder.storyImage.setVisible(true, true); } if (storiesList != null) { - PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); if (peerView != null) { int position = peerView.getSelectedPosition(); if (position >= 0 && position < storiesList.messageObjects.size()) { @@ -1656,7 +1683,7 @@ private void updateTransitionParams() { transitionViewHolder.storyImage.setAlpha(1f); transitionViewHolder.storyImage.setVisible(true, true); } - PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); int position = peerView == null ? 0 : peerView.getSelectedPosition(); int storyId = peerView == null || position < 0 || position >= peerView.storyItems.size() ? 0 : peerView.storyItems.get(position).id; TLRPC.StoryItem storyItem = peerView == null || position < 0 || position >= peerView.storyItems.size() ? null : peerView.storyItems.get(position); @@ -1759,7 +1786,7 @@ public void setOnCloseListener(Runnable listener) { } public boolean isPaused() { - return isPopupVisible || isBulletinVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible; + return isPopupVisible || isBulletinVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible || isInTextSelectionMode; } public void updatePlayingMode() { @@ -1792,7 +1819,7 @@ private boolean findClickableView(FrameLayout windowView, float x, float y, bool if (selfStoryViewsView != null && selfStoriesViewsOffset != 0) { return true; } - PeerStoriesView currentPeerView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView currentPeerView = storiesViewPager.getCurrentPeerView(); if (currentPeerView != null) { //fix view pager strange coordinates //just skip page.getX() @@ -1818,7 +1845,7 @@ private boolean findClickableView(FrameLayout windowView, float x, float y, bool } public boolean closeKeyboardOrEmoji() { - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { return peerStoriesView.closeKeyboardOrEmoji(); } @@ -1835,7 +1862,7 @@ private void updateProgressToDismiss() { if (progressToDismiss != newProgress) { progressToDismiss = newProgress; checkNavBarColor(); - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { peerStoriesView.progressToDismissUpdated(); } @@ -1854,7 +1881,7 @@ private void startOpenAnimation() { animationInProgress = true; fromDismissOffset = swipeToDismissOffset; if (transitionViewHolder.radialProgressUpload != null) { - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView != null && peerStoriesView.headerView.radialProgress != null) { peerStoriesView.headerView.radialProgress.copyParams(transitionViewHolder.radialProgressUpload); } @@ -1888,7 +1915,7 @@ public void onAnimationEnd(Animator animation) { transitionViewHolder.storyImage.setAlpha(1f); transitionViewHolder.storyImage.setVisible(true, true); } - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView != null) { peerStoriesView.updatePosition(); } @@ -1989,7 +2016,7 @@ public void onAnimationEnd(Animator animation) { transitionViewHolder.storyImage.setVisible(true, true); } if (transitionViewHolder.radialProgressUpload != null) { - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView != null && peerStoriesView.headerView.radialProgress != null) { transitionViewHolder.radialProgressUpload.copyParams(peerStoriesView.headerView.radialProgress); } @@ -2146,8 +2173,13 @@ public FrameLayout getContainerView() { return containerView; } + @Nullable public FrameLayout getContainerForBulletin() { - return storiesViewPager.getCurrentPeerView().storyContainer; + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + return peerStoriesView.storyContainer; + } + return null; } public void startActivityForResult(Intent photoPickerIntent, int code) { @@ -2159,7 +2191,9 @@ public void startActivityForResult(Intent photoPickerIntent, int code) { public void onActivityResult(int requestCode, int resultCode, Intent data) { PeerStoriesView currentPeerView = storiesViewPager.getCurrentPeerView(); - currentPeerView.onActivityResult(requestCode, resultCode, data); + if (currentPeerView != null) { + currentPeerView.onActivityResult(requestCode, resultCode, data); + } } public void dispatchKeyEvent(KeyEvent event) { @@ -2193,7 +2227,10 @@ public float getProgressToSelfViews() { public void setSelfStoriesViewsOffset(float currentTranslation) { selfStoriesViewsOffset = currentTranslation; - storiesViewPager.getCurrentPeerView().invalidate(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.invalidate(); + } containerView.invalidate(); } @@ -2415,7 +2452,7 @@ public void onStateChanged(boolean playWhenReady, int playbackState) { if (firstFrameRendered && playbackState == ExoPlayer.STATE_BUFFERING) { logBuffering = true; AndroidUtilities.runOnUIThread(() -> { - PeerStoriesView storiesView = getCurrentPeerView(); + final PeerStoriesView storiesView = getCurrentPeerView(); if (storiesView != null && storiesView.currentStory.storyItem != null) { FileLog.d("StoryViewer displayed story buffering dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); } @@ -2424,7 +2461,7 @@ public void onStateChanged(boolean playWhenReady, int playbackState) { if (logBuffering && playbackState == ExoPlayer.STATE_READY) { logBuffering = false; AndroidUtilities.runOnUIThread(() -> { - PeerStoriesView storiesView = getCurrentPeerView(); + final PeerStoriesView storiesView = getCurrentPeerView(); if (storiesView != null && storiesView.currentStory.storyItem != null) { FileLog.d("StoryViewer displayed story playing dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); } @@ -2516,6 +2553,10 @@ boolean release(Runnable whenReleased) { } videoPlayer = null; }); + if (playerStubBitmap != null) { + AndroidUtilities.recycleBitmap(playerStubBitmap); + playerStubBitmap = null; + } return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java index 93048f72d7..64d528b2c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java @@ -137,16 +137,16 @@ private void onClick() { toast.hide(); toast = null; } + if (buildingVideo != null) { + buildingVideo.stop(true); + buildingVideo = null; + } if (prepare != null) { preparing = true; prepare.run(this::onClickInternal); } if (currentEntry.wouldBeVideo()) { downloadingVideo = true; - if (buildingVideo != null) { - buildingVideo.stop(true); - buildingVideo = null; - } toast = new PreparingVideoToast(getContext()); toast.setOnCancelListener(() -> { preparing = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java index 7ec1912d03..a368a5b416 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java @@ -315,6 +315,17 @@ public File getOriginalFile() { return file; } + private String ext(File file) { + if (file == null) { + return null; + } + String s = file.getPath(); + int i; + if ((i = s.lastIndexOf('.')) > 0) + return s.substring(i + 1); + return null; + } + public void updateFilter(PhotoFilterView filterView, Runnable whenDone) { clearFilter(); @@ -329,6 +340,9 @@ public void updateFilter(PhotoFilterView filterView, Runnable whenDone) { Bitmap bitmap = filterView.getBitmap(); if (bitmap == null) { + if (whenDone != null) { + whenDone.run(); + } return; } @@ -345,11 +359,13 @@ public void updateFilter(PhotoFilterView filterView, Runnable whenDone) { if (filterFile != null && filterFile.exists()) { filterFile.delete(); } - filterFile = makeCacheFile(currentAccount, "webp"); + String ext = ext(file); + final boolean supportTransparent = "png".equals(ext) || "webp".equals(ext); + filterFile = makeCacheFile(currentAccount, supportTransparent ? "webp" : "jpg"); if (whenDone == null) { try { FileOutputStream stream = new FileOutputStream(filterFile); - rotatedBitmap.compress(Bitmap.CompressFormat.WEBP, 90, stream); + rotatedBitmap.compress(supportTransparent ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG, 90, stream); } catch (Exception e) { FileLog.e(e); } @@ -358,14 +374,16 @@ public void updateFilter(PhotoFilterView filterView, Runnable whenDone) { Utilities.themeQueue.postRunnable(() -> { try { FileOutputStream stream = new FileOutputStream(filterFile); - rotatedBitmap.compress(Bitmap.CompressFormat.WEBP, 90, stream); + rotatedBitmap.compress(supportTransparent ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG, 90, stream); } catch (Exception e) { FileLog.e(e, false); - try { - FileOutputStream stream = new FileOutputStream(filterFile); - rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); - } catch (Exception e2) { - FileLog.e(e2, false); + if (supportTransparent) { + try { + FileOutputStream stream = new FileOutputStream(filterFile); + rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); + } catch (Exception e2) { + FileLog.e(e2, false); + } } } rotatedBitmap.recycle(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index dc85e775b5..48547aed37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -244,7 +244,7 @@ public static SourceView fromStoryViewer(StoryViewer storyViewer) { SourceView src = new SourceView() { @Override protected void show() { - PeerStoriesView peerView = storyViewer.getCurrentPeerView(); + final PeerStoriesView peerView = storyViewer.getCurrentPeerView(); if (peerView != null) { peerView.animateOut(false); } @@ -256,7 +256,7 @@ protected void show() { @Override protected void hide() { - PeerStoriesView peerView = storyViewer.getCurrentPeerView(); + final PeerStoriesView peerView = storyViewer.getCurrentPeerView(); if (peerView != null) { peerView.animateOut(true); } @@ -267,7 +267,7 @@ protected void hide() { } src.type = 1; src.rounding = dp(8); - PeerStoriesView peerView = storyViewer.getCurrentPeerView(); + final PeerStoriesView peerView = storyViewer.getCurrentPeerView(); if (peerView != null) { src.view = peerView.storyContainer; } @@ -3434,7 +3434,7 @@ private void onSwitchEditModeStart(int fromMode, int toMode) { captionEdit.keyboardNotifier.ignore(toMode != EDIT_MODE_NONE); // privacySelectorHint.hide(); Bulletin.hideVisible(); - if (photoFilterView != null && toMode == EDIT_MODE_FILTER) { + if (photoFilterView != null && fromMode == EDIT_MODE_FILTER) { applyFilter(null); } if (photoFilterEnhanceView != null) { @@ -3518,8 +3518,19 @@ private void createFilterPhotoView() { return; } - Bitmap photoBitmap = previewView.getPhotoBitmap(); - if (photoBitmap == null) { + Bitmap photoBitmap = null; + if (!outputEntry.isVideo) { + if (outputEntry.filterFile == null) { + photoBitmap = previewView.getPhotoBitmap(); + } else { + if (photoFilterBitmap != null) { + photoFilterBitmap.recycle(); + photoFilterBitmap = null; + } + photoBitmap = photoFilterBitmap = StoryEntry.getScaledBitmap(opts -> BitmapFactory.decodeFile(outputEntry.file.getAbsolutePath(), opts), AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y, true); + } + } + if (photoBitmap == null && !outputEntry.isVideo) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index fe8e1a64fa..1998a851f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -4860,7 +4860,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View view; if (viewType == 0) { - view = new ChatMessageCell(mContext, false, new Theme.ResourcesProvider() { + view = new ChatMessageCell(mContext, false, null, new Theme.ResourcesProvider() { @Override public int getColor(int key) { return getThemedColor(key); diff --git a/gradle.properties b/gradle.properties index c9cef59e79..0071896fef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,8 +13,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sat Mar 12 05:53:50 MSK 2016 -APP_VERSION_CODE=3712 -APP_VERSION_NAME=9.7.4 +APP_VERSION_CODE=3721 +APP_VERSION_NAME=9.7.6 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=android RELEASE_KEY_ALIAS=androidkey