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 0651dd8bf..b21266ec7 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 @@ import com.google.common.collect.ImmutableList; 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 815656395..f9d991e72 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 final class DefaultMediaCodecAdapterFactory implements MediaCodecAdapter. @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 5c23d442f..2a9849f91 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.InputStream; 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 class AndroidUtilities { 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 class AndroidUtilities { } 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 class AndroidUtilities { 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 class AndroidUtilities { 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 5bd738ddf..6c9ff9cf5 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 000000000..72e85a460 --- /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 9856334c1..f118c0e92 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 class DispatchQueue extends Thread { } 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 class DispatchQueue extends Thread { 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 5a1313860..8ac61b73c 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 @@ public class FileLoadOperation { 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 278a4cd56..a6e3b6ee8 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 @@ public class FileLog { privateFields.add("networkType"); privateFields.add("disableFree"); privateFields.add("mContext"); + privateFields.add("priority"); //exclude file loading excludeRequests = new HashSet<>(); @@ -183,7 +184,7 @@ public class FileLog { @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 61ea8111d..18f019fc4 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 class FileStreamLoadOperation extends BaseDataSource implements FileLoadO @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 class FileStreamLoadOperation extends BaseDataSource implements FileLoadO return C.RESULT_END_OF_INPUT; } else { int availableLength = 0; + int bytesRead; try { if (bytesRemaining < readLength) { readLength = (int) bytesRemaining; @@ -165,14 +167,16 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO 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 6a8df8621..e0e3530d1 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.BackgroundGradientDrawable; 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 @@ import java.util.zip.GZIPInputStream; */ 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 class ImageLoader { 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 class 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 @@ public class ImageLoader { smallImagesMemCache = new LruCache(smallImagesCacheSize) { @Override protected int sizeOf(String key, BitmapDrawable value) { - return value.getBitmap().getByteCount(); + return sizeOfBitmapDrawable(value); } @Override @@ -2109,18 +2112,18 @@ public class ImageLoader { } } }; - 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 class ImageLoader { 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 7c0ffe9e2..9b48fddca 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.Bitmap; 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 @@ import java.util.List; 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 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private int thumbTag; private Drawable currentThumbDrawable; public BitmapShader thumbShader; + public BitmapShader staticThumbShader; private int thumbOrientation, thumbInvert; private ImageLocation currentMediaLocation; @@ -284,21 +288,20 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg imageShader = null; composeShader = null; thumbShader = null; + staticThumbShader = null; mediaShader = null; legacyShader = null; legacyCanvas = null; @@ -819,7 +823,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } fileDrawable.setAllowDecodeSingleFrame(true); } + staticThumbShader = null; thumbShader = null; roundPaint.setShader(null); setStaticDrawable(bitmap); @@ -937,8 +942,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg // 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg BitmapShader imageShader; Drawable currentThumbDrawable; BitmapShader thumbShader; + BitmapShader staticThumbShader; boolean crossfadeWithOldImage; boolean crossfadingWithThumb; @@ -1830,6 +1821,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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,20 +1886,20 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg shaderToUse = crossfadeShader; orientation = imageOrientation; invert = imageInvert; - } else if (staticThumbDrawable instanceof BitmapDrawable) { - drawable = staticThumbDrawable; - if (useRoundForThumb && thumbShader == null) { - updateDrawableRadius(staticThumbDrawable); - thumbShader = this.thumbShader; - } - shaderToUse = thumbShader; - orientation = thumbOrientation; - invert = thumbInvert; } else if (currentThumbDrawable != null) { drawable = currentThumbDrawable; shaderToUse = thumbShader; orientation = thumbOrientation; invert = thumbInvert; + } else if (staticThumbDrawable instanceof BitmapDrawable) { + drawable = staticThumbDrawable; + if (useRoundForThumb && staticThumbShader == null) { + updateDrawableRadius(staticThumbDrawable); + staticThumbShader = this.staticThumbShader; + } + shaderToUse = staticThumbShader; + orientation = thumbOrientation; + invert = thumbInvert; } float crossfadeProgress = currentAlpha; @@ -1932,17 +1910,17 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentThumbKey = null; currentThumbDrawable = null; thumbShader = null; + staticThumbShader = null; roundPaint.setShader(null); setStaticDrawable(thumb); crossfadeWithThumb = true; @@ -3123,6 +3102,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 class ImageReceiver implements NotificationCenter.NotificationCenterDeleg 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 5e0d1029d..5b28b1331 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 @@ public class MediaDataController extends BaseController { } public static long calcHash(long hash, long id) { - hash ^= id >> 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 000000000..6e7421ae5 --- /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 2f9a44f17..120700542 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 @@ public class MessageObject { } public void createStrippedThumb() { - if (photoThumbs == null || !canCreateStripedThubms() && !hasExtendedMediaPreview()) { + if (photoThumbs == null || !canCreateStripedThubms() && !hasExtendedMediaPreview() || strippedThumb != null) { return; } try { @@ -4835,7 +4835,15 @@ public class MessageObject { } 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 class MessageObject { } 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 59c754526..e93769d90 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 class MessagesController extends BaseController implements NotificationCe } 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 @@ public class MessagesController extends BaseController implements NotificationCe } } } - 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 @@ public class MessagesController extends BaseController implements NotificationCe } } } - 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 @@ public class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe } } } - 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 class MessagesController extends BaseController implements NotificationCe } public void processLoadedMessages(TLRPC.messages_Messages messagesRes, int resCount, long dialogId, long mergeDialogId, int count, int max_id, int offset_date, boolean isCache, int classGuid, - int first_unread, int last_message_id, int unread_count, int last_date, int load_type, boolean isEnd, int mode, int threadMessageId, int loadIndex, boolean queryFromServer, int mentionsCount, boolean needProcess, boolean isTopic) { + int first_unread, int last_message_id, int unread_count, int last_date, int load_type, boolean isEnd, int mode, int threadMessageId, int loadIndex, boolean queryFromServer, int mentionsCount, boolean needProcess, boolean isTopic, MessageLoaderLogger loaderLogger) { if (BuildVars.LOGS_ENABLED) { FileLog.d("processLoadedMessages size " + messagesRes.messages.size() + " in chat " + dialogId + " topic_id " + threadMessageId + " count " + count + " max_id " + max_id + " cache " + isCache + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer + " isTopic" + isTopic); } @@ -8242,16 +8245,16 @@ public class MessagesController extends BaseController implements NotificationCe reload = ((SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialogId, 0L)) > 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 class MessagesController extends BaseController implements NotificationCe 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 class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe } 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 class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe if (taskId != 0) { getMessagesStorage().removePendingTask(taskId); } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onReceivedChannelDifference, channelId); + }); return; } long newTaskId; @@ -12382,6 +12417,7 @@ public class MessagesController extends BaseController implements NotificationCe } 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 @@ public class MessagesController extends BaseController implements NotificationCe 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 @@ public class MessagesController extends BaseController implements NotificationCe 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 class MessagesController extends BaseController implements NotificationCe 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 class MessagesController extends BaseController implements NotificationCe 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 10a3cbf26..f15a4aa04 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 class MessagesStorage extends BaseController { }); } - 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 class MessagesStorage extends BaseController { }; } 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 @@ public class MessagesStorage extends BaseController { } } - 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 class MessagesStorage extends BaseController { }); } - 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 class MessagesStorage extends BaseController { 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 76cf3dfc4..0211c54e9 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 f9714e3ae..1c27888a3 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 @@ public class NotificationsController extends BaseController { 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 80c7cfe97..aa38edde1 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 class SaveToGallerySettingsHelper { } 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 class SaveToGallerySettingsHelper { } 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 1425baaf9..9b9bf2497 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 android.util.SparseArray; 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 class SvgHelper { 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 class SvgHelper { 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 class SvgHelper { 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 @@ public class SvgHelper { 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 class SvgHelper { 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 000000000..f4eb6887b --- /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 7be374934..3ee0b432e 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 class Theme { 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 class Theme { 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 @@ public class Theme { 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 class Theme { 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 class Theme { 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 class Theme { 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 class Theme { 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 class Theme { } 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 fe194b4db..e6d922214 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 android.widget.Toast; 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg tracker.recycle(); tracker = null; } - if (textSelectionHelper != null && !textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && !textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); } } @@ -1134,7 +1136,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 class ArticleViewer implements NotificationCenter.NotificationCenterDeleg }); listView[i].setOnItemClickListener((view, position, x, y) -> { if (textSelectionHelper != null) { - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); return; } @@ -4580,7 +4582,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return; } } - if (textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper.isInSelectionMode()) { textSelectionHelper.clear(); return; } @@ -7541,7 +7543,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg pressedLinkOwnerView = null; } updateChildTextPositions(); - if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { textSelectionHelper.invalidate(); } } @@ -10394,13 +10396,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg 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 5ece31b4d..83af78d8e 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 class CacheControlActivity extends BaseFragment implements NotificationCe 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 class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } } 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 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe 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 c33877c6f..8d2a8be2a 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.PhoneFormat.PhoneFormat; 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 class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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 class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } 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 class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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 c6c0a8ff6..eea62e77c 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.VectorAvatarThumbDrawable; 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 class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } }; - private Path thumbPath = new Path(); + private Path thumbPath; private SpoilerEffect thumbSpoiler = new SpoilerEffect(); public void setMoving(boolean moving) { @@ -708,6 +709,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava AnimatedEmojiSpan.release(this, animatedEmojiStack3); AnimatedEmojiSpan.release(this, animatedEmojiStackName); storyParams.onDetachFromWindow(); + canvasButton = null; } @Override @@ -3765,7 +3767,11 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava ); 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 class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } 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 bfcd3ff9e..4a50325a5 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.UserConfig; 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.CheckBox2; 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 class ProfileSearchCell extends BaseCell implements NotificationCenter.No } 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 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No actionLayout.draw(canvas); canvas.restore(); } - avatarImage.draw(canvas); + StoriesUtilities.drawAvatarWithStory(dialog_id, canvas, avatarImage, avatarStoryParams); } @Override @@ -790,6 +794,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No @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 284ea264a..b3559708e 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.Magnifier; 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 abstract class TextSelectionHelper= 0 && selectionEnd >= 0; } @@ -481,7 +491,7 @@ public abstract class TextSelectionHelper= 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 @@ public abstract class TextSelectionHelper 1) { return movingHandle; } @@ -747,8 +758,13 @@ public abstract class TextSelectionHelper 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 abstract class TextSelectionHelper= 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 @@ public abstract class TextSelectionHelper= 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 @@ public abstract class TextSelectionHelper 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 @@ public abstract class TextSelectionHelper layout.getText().length()) { return tmpCoord; @@ -1477,7 +1560,7 @@ public abstract class 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 @@ public abstract class TextSelectionHelper blocks); } + public interface SimpleSelectabeleView extends SelectableView { + + CharSequence getText(); + + Layout getStaticTextLayout(); + } + public interface SelectableView { int getBottom(); @@ -2886,10 +3079,10 @@ public abstract class TextSelectionHelper { + waitingForGetDifference = isGettingDifference; + if (!waitingForGetDifference) { + firstLoadMessages(); + } + }); + } else { + getMessagesController().startShortPoll(currentChat, classGuid, false); + } } } else if (userId != 0) { currentUser = getMessagesController().getUser(userId); @@ -2301,6 +2321,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - boolean loadInfo = false; + loadInfo = false; if (currentChat != null) { chatInfo = getMessagesController().getChatFull(currentChat.id); groupCall = getMessagesController().getGroupCall(currentChat.id, true); @@ -2382,35 +2403,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatAttachAlert != null) { chatAttachAlert.dismissInternal(); } + ContentPreviewViewer.getInstance().clearDelegate(contentPreviewViewerDelegate); getNotificationCenter().onAnimationFinish(transitionAnimationIndex); NotificationCenter.getGlobalInstance().onAnimationFinish(transitionAnimationGlobalIndex); getNotificationCenter().onAnimationFinish(scrollAnimationIndex); @@ -2656,6 +2687,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } forceScrollToTop = false; - if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { + if (textSelectionHelper != null && textSelectionHelper.isInSelectionMode()) { textSelectionHelper.invalidate(); } isSkeletonVisible(); @@ -3837,7 +3870,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }; 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not } 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 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } 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 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not clear = false; } } - if (clear) { + if (clear && !requestAnyway) { return; } } @@ -12123,7 +12158,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not } 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 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not }; 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 class ChatActivity extends BaseFragment implements NotificationCenter.Not 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 3f3e17149..bb080cba8 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 @@ public class AnimatedEmojiDrawable extends Drawable { } }; 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 e6c8f890b..2ee416349 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.Shader; 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, public void setIsWebmSticker(boolean b) { isWebmSticker = b; + PRERENDER_FRAME = false; if (isWebmSticker) { useSharedQueue = true; } @@ -750,7 +766,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, 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); + if (USE_BITMAP_SHADER) { + canvas.drawPath(path, paint); + } else { + canvas.save(); + canvas.clipPath(path); + drawBitmap(rect, paint, canvas, scaleX, scaleY); + canvas.restore(); + } } 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); - } - canvas.scale(scaleX, scaleY); - canvas.drawBitmap(renderingBitmap, 0, 0, paint); + 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 class AnimatedFileDrawable extends BitmapDrawable implements Animatable, public void setLimitFps(boolean limitFps) { this.limitFps = limitFps; + if (limitFps) { + PRERENDER_FRAME = false; + } } public ArrayList getParents() { @@ -1225,4 +1257,12 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, 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 d55c7671e..9e61dfa0a 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 class CacheChart extends View { 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 cfa816d7b..36730d03c 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 class ChatActivityEnterView extends BlurredFrameLayout implements Notific 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 789826a8e..e09a5cb36 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 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific 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 5ef44b979..3d6d2e442 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 androidx.recyclerview.widget.RecyclerView; 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 class ForwardingPreviewView extends FrameLayout { ArrayList actionItems = new ArrayList<>(); Rect rect = new Rect(); + ChatMessageSharedResources sharedResources; private boolean firstLayout = true; ValueAnimator offsetsAnimator; @@ -116,6 +118,7 @@ public class ForwardingPreviewView extends FrameLayout { @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 class ForwardingPreviewView extends FrameLayout { } 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 61377e4dd..fa4a45f46 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter @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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } } 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } } else { if (BuildVars.LOGS_ENABLED) { - FileLog.e("failed creating shader"); + FileLog.e("InstantCamera failed creating shader"); } finish(); return false; @@ -1454,7 +1440,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter } 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter } 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter } 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter } } - 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter generateKeyframeThumbsQueue.recycle(); generateKeyframeThumbsQueue = null; } + FileLog.d("InstantCamera handleStopRecording send " + send); if (send != 0) { AndroidUtilities.runOnUIThread(() -> { videoEditedInfo = new VideoEditedInfo(); @@ -2486,7 +2506,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 class InstantCameraView extends FrameLayout implements NotificationCenter 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 5cc3b6cff..685469bbf 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 class PremiumLockIconView extends ImageView { } private void updateGradient() { + if (!attachedToWindow) { + return; + } if (getMeasuredHeight() != 0 && getMeasuredWidth() != 0) { int c1 = currentColor; int c2; @@ -192,6 +196,27 @@ public class PremiumLockIconView extends ImageView { } } + @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 2feca26b3..18a855176 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 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi 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 1e1066dde..25799cfb7 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 class SpoilerEffect extends Drawable { 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 fc1ac7efa..7b6a3a473 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 class SpoilerEffectBitmapFactory { 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 class SpoilerEffectBitmapFactory { 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 6f802432a..0e79b4ff1 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.Rect; 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 @@ public class SpoilersTextView extends TextView { } 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 f93799109..db22d390c 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 class ContentPreviewViewer { 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 @@ public class ContentPreviewViewer { 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 class ContentPreviewViewer { 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 @@ public class ContentPreviewViewer { 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 b4ffed892..c939b27b2 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 class DataSettingsActivity extends BaseFragment { 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 2215cedcd..63ca8d76c 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.Build; 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 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. 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 class DialogsActivity extends BaseFragment implements NotificationCenter. 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 class DialogsActivity extends BaseFragment implements NotificationCenter. } 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 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. // } 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 class DialogsActivity extends BaseFragment implements NotificationCenter. @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 9d5355e1a..b3287f2f5 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.ActionBar.Theme; 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 class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }; + @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 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat 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 class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return false; }); - captionLimitView = new TextView(parentActivity); captionLimitView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); captionLimitView.setTextColor(0xffEC7777); @@ -7025,6 +7055,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat 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 class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } 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 class PhotoViewer implements NotificationCenter.NotificationCenterDelegat 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 class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return bottomTouchEnabled && b; } + @Override public void setPressed(boolean pressed) { final boolean needsRefresh = pressed != isPressed(); @@ -7465,6 +7511,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @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 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat 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 29df80b3b..72c901891 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 class SaveToGallerySettingsActivity extends BaseFragment { 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 class SaveToGallerySettingsActivity extends BaseFragment { 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 class SaveToGallerySettingsActivity extends BaseFragment { } 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 f2be15832..8cea04c7b 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 class StatisticActivity extends BaseFragment implements NotificationCente 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 951ba834e..593170db3 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 class DarkThemeResourceProvider implements Theme.ResourcesProvider { 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 a02920bbc..b98156487 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.PorterDuffColorFilter; 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.LayoutHelper; 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 class DialogStoriesCell extends FrameLayout implements NotificationCenter 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 class DialogStoriesCell extends FrameLayout implements NotificationCenter 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 class DialogStoriesCell extends FrameLayout implements NotificationCenter public void setCrossfadeTo(long dialogId) { if (crossfadeToDialogId != dialogId) { + this.crossfadeToDialogId = dialogId; crossfadeToDialog = dialogId != -1; if (crossfadeToDialog) { TLObject object; @@ -1604,12 +1616,18 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter .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 93e4859ad..c4ac21db8 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.BaseFragment; 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 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public boolean closeKeyboardOrEmoji() { + if (storyCaptionView.textSelectionHelper.isInSelectionMode()) { + storyCaptionView.textSelectionHelper.clear(false); + return true; + } if (privacyHint != null) { privacyHint.hide(); } @@ -3149,6 +3164,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica //storyViewer.allowScreenshots(allowScreenshots); } else { + cancelTextSelection(); muteIconView.clearAnimationDrawable(); viewsThumbImageReceiver = null; isLongPressed = false; @@ -3196,6 +3212,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica progressToHideInterface.set(0, false); viewsThumbImageReceiver = null; messageSent = false; + cancelTextSelection(); } public void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -3377,6 +3394,26 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica void setIsHintVisible(boolean visible); void setIsSwiping(boolean swiping); + + void setIsInSelectionMode(boolean selectionMode); } public class StoryItemHolder { @@ -4006,6 +4045,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica return; } + if (reactionsContainerLayout != null) { reactionsContainerLayout.setVisibility(progressToKeyboard > 0 ? View.VISIBLE : View.GONE); } @@ -4031,7 +4077,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica 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 bc59e1192..a5d8290d5 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 class SelfStoryViewsPage extends FrameLayout implements NotificationCente 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 class SelfStoryViewsPage extends FrameLayout implements NotificationCente 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 db0e06e57..e2d250eee 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 class SelfStoryViewsView extends FrameLayout { 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 9b8be57e4..a18df5b67 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.ActionBar.Theme; 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 class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { 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 07550cdb9..dc39fb335 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.UserConfig; 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.ButtonBounce; 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 class StoriesUtilities { 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 class StoriesUtilities { } 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 class StoriesUtilities { 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 class StoriesUtilities { 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 class StoriesUtilities { 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 @@ public class StoriesUtilities { 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 @@ public class StoriesUtilities { } 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 8a197f7e6..b66ac70ac 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.view.ViewGroup; 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 class StoriesViewPager extends ViewPager { @Override public void onPageSelected(int position) { - PeerStoriesView peerStoriesView = getCurrentPeerView(); + final PeerStoriesView peerStoriesView = getCurrentPeerView(); if (peerStoriesView == null) { return; } @@ -222,6 +223,7 @@ public class StoriesViewPager extends ViewPager { return true; } + @Nullable public PeerStoriesView getCurrentPeerView() { for (int i = 0; i < getChildCount(); i++) { if ((Integer) getChildAt(i).getTag() == getCurrentItem()) { @@ -264,7 +266,7 @@ public class StoriesViewPager extends ViewPager { 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 class StoriesViewPager extends ViewPager { 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 3fd7df309..67392a842 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.R; 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 class StoryCaptionView extends NestedScrollView { 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 class StoryCaptionView extends NestedScrollView { } captionTextview.setTranslationY(overScrollY); + textSelectionHelper.invalidate(); return true; } @@ -359,6 +363,7 @@ public class StoryCaptionView extends NestedScrollView { } } } + textSelectionHelper.invalidate(); } private void startSpringAnimationIfNotRunning(float velocityY) { @@ -466,6 +471,7 @@ public class StoryCaptionView extends NestedScrollView { if (getParent() != null) { ((View) getParent()).invalidate(); } + textSelectionHelper.invalidate(); } public float getProgressToBlackout() { @@ -539,7 +545,13 @@ public class StoryCaptionView extends NestedScrollView { 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 StoryCaptionView extends NestedScrollView { int textHeight; float textX; float textY; - boolean expanded = false; float progressToExpand; float showMoreY; float showMoreX; @@ -621,7 +632,11 @@ public class StoryCaptionView extends NestedScrollView { // invalidateSpoilers(); this.text = text; sizeCached = 0; + if (getMeasuredWidth() > 0) { + createLayout(getMeasuredWidth()); + } requestLayout(); + invalidate(); } @SuppressLint("DrawAllocation") @@ -632,65 +647,69 @@ public class StoryCaptionView extends NestedScrollView { 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); - } - } - 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); - } + 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; + } + } + } + } else { + showMore = null; + firstLayout = null; + spoilersPool.addAll(spoilers); + spoilers.clear(); + SpoilerEffect.addSpoilers(this, fullLayout, spoilersPool, spoilers); + } + } + @Override protected void onDraw(Canvas canvas) { if (showMore != null) { @@ -710,12 +729,21 @@ public class StoryCaptionView extends NestedScrollView { 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 class StoryCaptionView extends NestedScrollView { 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 class StoryCaptionView extends NestedScrollView { @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 class StoryCaptionView extends NestedScrollView { } } 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 6d39b01d2..62fe0795f 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.graphics.SurfaceTexture; 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.view.WindowManager; 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 org.telegram.ui.LaunchActivity; 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 class StoryViewer { 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 class StoryViewer { @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 class StoryViewer { } if (ev.getAction() == MotionEvent.ACTION_DOWN) { swipeToReplyWaitingKeyboard = false; - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { peerStoriesView.onActionDown(ev); } @@ -812,14 +815,11 @@ public class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { updatePlayingMode(); } + @Override + public void setIsInSelectionMode(boolean selectionMode) { + StoryViewer.this.isInTextSelectionMode = selectionMode; + updatePlayingMode(); + } + @Override public int getKeyboardHeight() { return realKeyboardHeight; @@ -1452,10 +1461,11 @@ public class StoryViewer { } 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 class StoryViewer { 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 class StoryViewer { 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 @@ public class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { return true; } + @Nullable public PeerStoriesView getCurrentPeerView() { if (storiesViewPager == null) { return null; @@ -1604,8 +1629,10 @@ public class StoryViewer { 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 @@ public class StoryViewer { 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 @@ public class StoryViewer { 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 class StoryViewer { } 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 @@ public class StoryViewer { 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 @@ public class StoryViewer { } public boolean closeKeyboardOrEmoji() { - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { return peerStoriesView.closeKeyboardOrEmoji(); } @@ -1835,7 +1862,7 @@ public class StoryViewer { if (progressToDismiss != newProgress) { progressToDismiss = newProgress; checkNavBarColor(); - PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + final PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { peerStoriesView.progressToDismissUpdated(); } @@ -1854,7 +1881,7 @@ public class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 class StoryViewer { 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 @@ public class StoryViewer { } 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 93048f72d..64d528b2c 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 @@ public class DownloadButton extends ImageView { 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 7ec1912d0..a368a5b41 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 class StoryEntry extends IStoryPart { 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 class StoryEntry extends IStoryPart { Bitmap bitmap = filterView.getBitmap(); if (bitmap == null) { + if (whenDone != null) { + whenDone.run(); + } return; } @@ -345,11 +359,13 @@ public class StoryEntry extends IStoryPart { 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 class StoryEntry extends IStoryPart { 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 dc85e775b..48547aed3 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 class StoryRecorder implements NotificationCenter.NotificationCenterDeleg 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 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg @Override protected void hide() { - PeerStoriesView peerView = storyViewer.getCurrentPeerView(); + final PeerStoriesView peerView = storyViewer.getCurrentPeerView(); if (peerView != null) { peerView.animateOut(true); } @@ -267,7 +267,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } 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 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg 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 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg 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 fe8e1a64f..1998a851f 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 class ThemePreviewActivity extends BaseFragment implements DownloadContro 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 c9cef59e7..0071896fe 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