From f10844350d08f11aaae870a7025d47d5518c29c0 Mon Sep 17 00:00:00 2001 From: xaxtix Date: Sat, 22 Jul 2023 05:33:39 +0400 Subject: [PATCH] update to 9.7.2 (3705) --- .../org/telegram/DispatchQueuePriority.java | 43 +- .../telegram/messenger/AndroidUtilities.java | 48 +- .../org/telegram/messenger/BuildVars.java | 4 +- .../org/telegram/messenger/DispatchQueue.java | 15 + .../telegram/messenger/DispatchQueuePool.java | 7 + .../DispatchQueuePoolBackground.java | 7 + .../telegram/messenger/FileLoadOperation.java | 4 +- .../org/telegram/messenger/FileLoader.java | 2 +- .../messenger/FileLoaderPriorityQueue.java | 9 + .../java/org/telegram/messenger/FileLog.java | 11 +- .../telegram/messenger/FileRefController.java | 28 +- .../messenger/FileStreamLoadOperation.java | 13 +- .../org/telegram/messenger/ImageLoader.java | 62 +- .../org/telegram/messenger/ImageReceiver.java | 23 +- .../messenger/MessagesController.java | 5 +- .../telegram/messenger/MessagesStorage.java | 2 - .../messenger/NotificationsController.java | 12 +- .../messenger/PushListenerController.java | 2 +- .../RuntimeClassNameTypeAdapterFactory.java | 14 +- .../messenger/camera/CameraController.java | 1 + .../telegram/messenger/camera/CameraView.java | 97 +-- .../ui/ActionBar/ActionBarLayout.java | 1 + .../ui/ActionBar/ActionBarPopupWindow.java | 23 +- .../telegram/ui/Adapters/ContactsAdapter.java | 27 +- .../telegram/ui/Adapters/DialogsAdapter.java | 29 +- .../ui/Adapters/DrawerLayoutAdapter.java | 8 +- .../telegram/ui/Cells/AudioPlayerCell.java | 2 +- .../org/telegram/ui/Cells/ChatActionCell.java | 4 +- .../telegram/ui/Cells/ChatMessageCell.java | 1 + .../org/telegram/ui/Cells/DialogCell.java | 62 +- .../telegram/ui/Cells/DrawerProfileCell.java | 36 +- .../org/telegram/ui/Cells/DrawerUserCell.java | 2 + .../telegram/ui/Cells/SharedAudioCell.java | 4 +- .../telegram/ui/Cells/SharedDocumentCell.java | 4 +- .../org/telegram/ui/Cells/SharedLinkCell.java | 2 +- .../java/org/telegram/ui/Cells/UserCell.java | 11 +- .../java/org/telegram/ui/ChatActivity.java | 7 +- .../ui/Components/AnimatedEmojiDrawable.java | 156 +++-- .../ui/Components/AnimatedTextView.java | 79 +++ .../ui/Components/BackupImageView.java | 6 +- .../ChatAttachAlertDocumentLayout.java | 10 + .../ChatScrimPopupContainerLayout.java | 6 +- .../ui/Components/ColoredImageSpan.java | 2 +- .../telegram/ui/Components/Crop/CropView.java | 3 + .../ui/Components/EllipsizeSpanAnimator.java | 6 +- .../ui/Components/EmojiTabsStrip.java | 98 ++- .../org/telegram/ui/Components/EmojiView.java | 4 +- .../ui/Components/InstantCameraView.java | 135 ++-- .../telegram/ui/Components/ItemOptions.java | 3 +- .../telegram/ui/Components/MediaActivity.java | 7 +- .../Components/Paint/PersistColorPalette.java | 24 +- .../Paint/Views/EditTextOutline.java | 5 +- .../ui/Components/PaintingOverlay.java | 25 +- .../PhotoViewerCaptionEnterView.java | 4 + .../Components/Premium/PremiumButtonView.java | 1 + .../Reactions/CustomEmojiReactionsWindow.java | 220 +++++-- .../ui/Components/Reactions/HwEmojis.java | 106 ++++ .../Components/ReactionsContainerLayout.java | 188 +++++- .../ui/Components/RecyclerListView.java | 8 +- .../ui/Components/SharedMediaLayout.java | 18 +- .../ui/Components/StableAnimator.java | 68 +++ .../ui/Components/StaticLayoutEx.java | 6 + .../Components/StickerCategoriesListView.java | 30 +- .../telegram/ui/Components/VideoPlayer.java | 2 - .../spoilers/SpoilerEffectBitmapFactory.java | 3 +- .../java/org/telegram/ui/DialogsActivity.java | 34 +- .../org/telegram/ui/FilteredSearchView.java | 50 +- .../java/org/telegram/ui/LaunchActivity.java | 6 +- .../java/org/telegram/ui/PhotoViewer.java | 2 +- .../java/org/telegram/ui/ProfileActivity.java | 2 + .../ui/SelectAnimatedEmojiDialog.java | 574 +++++++++++++----- .../telegram/ui/SponsoredMessageInfoView.java | 30 +- .../ui/Stories/DialogStoriesCell.java | 15 +- .../telegram/ui/Stories/PeerStoriesView.java | 106 ++-- .../ui/Stories/ProfileStoriesView.java | 4 +- .../ui/Stories/SelfStoryViewsPage.java | 16 +- .../ui/Stories/StoriesController.java | 29 +- .../ui/Stories/StoriesListPlaceProvider.java | 29 +- .../telegram/ui/Stories/StoriesUtilities.java | 69 ++- .../telegram/ui/Stories/StoriesViewPager.java | 1 + .../telegram/ui/Stories/StoryCaptionView.java | 17 +- .../ui/Stories/StoryContainsEmojiButton.java | 10 +- .../org/telegram/ui/Stories/StoryViewer.java | 127 ++-- .../ui/Stories/recorder/DraftSavedHint.java | 1 + .../ui/Stories/recorder/DualCameraView.java | 16 + .../ui/Stories/recorder/EmojiBottomSheet.java | 6 +- .../ui/Stories/recorder/GalleryListView.java | 2 +- .../ui/Stories/recorder/HintTextView.java | 7 + .../ui/Stories/recorder/HintView2.java | 23 +- .../ui/Stories/recorder/PaintView.java | 47 +- .../ui/Stories/recorder/PreviewView.java | 24 +- .../ui/Stories/recorder/StoryEntry.java | 4 +- .../recorder/StoryPrivacyBottomSheet.java | 29 +- .../ui/Stories/recorder/StoryRecorder.java | 46 +- .../ui/Stories/recorder/TrashView.java | 4 +- .../msg_mini_arrow_mediabold.png | Bin 0 -> 335 bytes .../msg_mini_arrow_mediathin.png | Bin 0 -> 315 bytes .../msg_mini_arrow_mediabold.png | Bin 0 -> 280 bytes .../msg_mini_arrow_mediathin.png | Bin 0 -> 273 bytes .../msg_mini_arrow_mediabold.png | Bin 0 -> 394 bytes .../msg_mini_arrow_mediathin.png | Bin 0 -> 374 bytes .../msg_mini_arrow_mediabold.png | Bin 0 -> 517 bytes .../msg_mini_arrow_mediathin.png | Bin 0 -> 471 bytes .../src/main/res/raw/camera_frag.glsl | 22 +- TMessagesProj/src/main/res/values/strings.xml | 43 +- gradle.properties | 4 +- 106 files changed, 2383 insertions(+), 871 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/HwEmojis.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/StableAnimator.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_mini_arrow_mediabold.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_mini_arrow_mediathin.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediabold.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediathin.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediabold.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediathin.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_arrow_mediabold.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_arrow_mediathin.png diff --git a/TMessagesProj/src/main/java/org/telegram/DispatchQueuePriority.java b/TMessagesProj/src/main/java/org/telegram/DispatchQueuePriority.java index 37d83951e..29d67c7fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/DispatchQueuePriority.java +++ b/TMessagesProj/src/main/java/org/telegram/DispatchQueuePriority.java @@ -1,6 +1,9 @@ package org.telegram; +import org.telegram.messenger.FileLog; + import java.util.Comparator; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -21,8 +24,21 @@ public class DispatchQueuePriority { } return priority2 - priority1; } - })); + })) { + @Override + protected void beforeExecute(Thread t, Runnable r) { + CountDownLatch latch = pauseLatch; + if (latch != null) { + try { + latch.await(); + } catch (InterruptedException e) { + FileLog.e(e); + } + } + } + }; + private volatile CountDownLatch pauseLatch; public DispatchQueuePriority(String threadName) { @@ -41,15 +57,11 @@ public class DispatchQueuePriority { } public Runnable postRunnable(Runnable runnable, int priority) { - if (priority == 1) { - postRunnable(runnable); - return runnable; - } else { - PriorityRunnable priorityRunnable = new PriorityRunnable(priority, runnable); - - threadPoolExecutor.execute(priorityRunnable); - return priorityRunnable; + if (priority != 1) { + runnable = new PriorityRunnable(priority, runnable); } + postRunnable(runnable); + return runnable; } public void cancelRunnable(Runnable runnable) { @@ -57,7 +69,20 @@ public class DispatchQueuePriority { return; } threadPoolExecutor.remove(runnable); + } + public void pause() { + if (pauseLatch == null) { + pauseLatch = new CountDownLatch(1); + } + } + + public void resume() { + CountDownLatch latch = pauseLatch; + if (latch != null) { + latch.countDown(); + pauseLatch = null; + } } private static class PriorityRunnable implements Runnable { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index f2bb8daf7..f5f4fc775 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -99,7 +99,6 @@ import android.view.inputmethod.InputMethodSubtype; import android.view.inspector.WindowInspector; import android.webkit.MimeTypeMap; import android.widget.EdgeEffect; -import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; @@ -123,7 +122,6 @@ import androidx.viewpager.widget.ViewPager; import com.android.internal.telephony.ITelephony; import com.google.android.exoplayer2.util.Consumer; -import com.google.android.exoplayer2.util.Log; import com.google.android.gms.auth.api.phone.SmsRetriever; import com.google.android.gms.auth.api.phone.SmsRetrieverClient; import com.google.android.gms.tasks.Task; @@ -155,7 +153,6 @@ import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ShareAlert; -import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanReplacement; import org.telegram.ui.Components.UndoView; @@ -177,7 +174,6 @@ 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; @@ -196,7 +192,6 @@ import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -590,7 +585,7 @@ public class AndroidUtilities { } public static void removeFromParent(View child) { - if (child.getParent() != null) { + if (child != null && child.getParent() != null) { ((ViewGroup) child.getParent()).removeView(child); } } @@ -2750,6 +2745,39 @@ public class AndroidUtilities { return new SpannableStringBuilder(str); } + private static Pattern linksPattern; + public static SpannableStringBuilder replaceLinks(String str, Theme.ResourcesProvider resourcesProvider) { + if (linksPattern == null) { + linksPattern = Pattern.compile("\\[(.+?)\\]\\((.+?)\\)"); + } + SpannableStringBuilder spannable = new SpannableStringBuilder(); + Matcher matcher = linksPattern.matcher(str); + int lastMatchEnd = 0; + while (matcher.find()) { + spannable.append(str, lastMatchEnd, matcher.start()); + String linkText = matcher.group(1); + String url = matcher.group(2); + spannable.append(linkText); + int start = spannable.length() - linkText.length(); + int end = spannable.length(); + spannable.setSpan(new ClickableSpan() { + @Override + public void onClick(@NonNull View widget) { + Browser.openUrl(ApplicationLoader.applicationContext, url); + } + @Override + public void updateDrawState(@NonNull TextPaint ds) { + ds.setColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + ds.setUnderlineText(false); + } + }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + lastMatchEnd = matcher.end(); + } + spannable.append(str, lastMatchEnd, str.length()); + return spannable; + } + public static class LinkMovementMethodMy extends LinkMovementMethod { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { @@ -5324,4 +5352,12 @@ public class AndroidUtilities { } catch (Exception ignore) {} return ""; } + + public static void quietSleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException ignored) { + + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 13df6e507..5ef4036db 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 = 3687; - public static String BUILD_VERSION_STRING = "9.7.0"; + public static int BUILD_VERSION = 3705; + public static String BUILD_VERSION_STRING = "9.7.2"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index d57bdaa58..9856334c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -11,17 +11,21 @@ package org.telegram.messenger; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.SystemClock; import java.util.concurrent.CountDownLatch; public class DispatchQueue extends Thread { + private static final int THREAD_PRIORITY_DEFAULT = -1000; + private volatile Handler handler = null; private CountDownLatch syncLatch = new CountDownLatch(1); private long lastTaskTime; private static int indexPointer = 0; public final int index = indexPointer++; + private int priority = THREAD_PRIORITY_DEFAULT; public DispatchQueue(final String threadName) { this(threadName, true); @@ -34,6 +38,14 @@ public class DispatchQueue extends Thread { } } + public DispatchQueue(final String threadName, boolean start, int priority) { + this.priority = priority; + setName(threadName); + if (start) { + start(); + } + } + public void sendMessage(Message msg, int delay) { try { syncLatch.await(); @@ -114,6 +126,9 @@ public class DispatchQueue extends Thread { return true; }); syncLatch.countDown(); + if (priority != THREAD_PRIORITY_DEFAULT) { + Process.setThreadPriority(priority); + } Looper.loop(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePool.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePool.java index 58479eecd..2a6d1ecc6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePool.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePool.java @@ -5,6 +5,8 @@ import android.util.SparseIntArray; import androidx.annotation.UiThread; +import org.telegram.ui.Components.Reactions.HwEmojis; + import java.util.LinkedList; public class DispatchQueuePool { @@ -68,6 +70,11 @@ public class DispatchQueuePool { busyQueues.add(queue); int count = busyQueuesMap.get(queue.index, 0); busyQueuesMap.put(queue.index, count + 1); + if (HwEmojis.isHwEnabled()) { + queue.setPriority(Thread.MIN_PRIORITY); + } else if (queue.getPriority() != Thread.MAX_PRIORITY) { + queue.setPriority(Thread.MAX_PRIORITY); + } queue.postRunnable(() -> { runnable.run(); AndroidUtilities.runOnUIThread(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolBackground.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolBackground.java index 185143c82..75a272e95 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolBackground.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolBackground.java @@ -5,6 +5,8 @@ import android.util.SparseIntArray; import androidx.annotation.UiThread; +import org.telegram.ui.Components.Reactions.HwEmojis; + import java.util.ArrayList; public class DispatchQueuePoolBackground { @@ -77,6 +79,11 @@ public class DispatchQueuePoolBackground { busyQueues.add(queue); int count = busyQueuesMap.get(queue.index, 0); busyQueuesMap.put(queue.index, count + 1); + if(HwEmojis.isHwEnabled()) { + queue.setPriority(Thread.MIN_PRIORITY); + } else if (queue.getPriority() != Thread.MAX_PRIORITY) { + queue.setPriority(Thread.MAX_PRIORITY); + } queue.postRunnable(() -> { runnable.run(); Utilities.globalQueue.postRunnable(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index dfdef5678..058f9c73f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -638,7 +638,7 @@ public class FileLoadOperation { final CountDownLatch countDownLatch = new CountDownLatch(1); final File[] result = new File[1]; Utilities.stageQueue.postRunnable(() -> { - if (state == stateFinished) { + if (state == stateFinished && !preloadFinished) { result[0] = cacheFileFinal; } else { result[0] = cacheFileTemp; @@ -654,7 +654,7 @@ public class FileLoadOperation { } protected File getCurrentFileFast() { - if (state == stateFinished) { + if (state == stateFinished && !preloadFinished) { return cacheFileFinal; } else { return cacheFileTemp; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index f511c54f6..a03b4eb20 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -938,7 +938,7 @@ public class FileLoader extends BaseController { } loaderQueue.add(operation); - loaderQueue.checkLoadingOperations(); + loaderQueue.checkLoadingOperations(operation.isStory && priority >= PRIORITY_HIGH); if (BuildVars.LOGS_ENABLED) { FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java index dfc284e32..820b2c4e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java @@ -69,6 +69,15 @@ public class FileLoaderPriorityQueue { } public void checkLoadingOperations() { + checkLoadingOperations(false); + } + + public void checkLoadingOperations(boolean immediate) { + if (immediate) { + workerQueue.cancelRunnable(checkOperationsRunnable); + checkOperationsRunnable.run(); + return; + } if (checkOperationsScheduled) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 8a09dd6a0..278a4cd56 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -21,6 +21,7 @@ import org.telegram.messenger.time.FastDateFormat; import org.telegram.messenger.video.MediaCodecVideoConvertor; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.LaunchActivity; import java.io.File; @@ -170,7 +171,7 @@ public class FileLog { excludeRequests.add("TL_upload_getFile"); excludeRequests.add("TL_upload_a"); - gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() { + ExclusionStrategy strategy = new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { @@ -182,12 +183,10 @@ public class FileLog { @Override public boolean shouldSkipClass(Class clazz) { - if (clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class)) { - return true; - } - return false; + return clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class); } - }).registerTypeAdapterFactory(RuntimeClassNameTypeAdapterFactory.of(TLObject.class, "type_")).create(); + }; + gson = new GsonBuilder().addSerializationExclusionStrategy(strategy).registerTypeAdapterFactory(RuntimeClassNameTypeAdapterFactory.of(TLObject.class, "type_", strategy)).create(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 42aec392f..698fc0e8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -1059,19 +1059,21 @@ public class FileRefController extends BaseController { Object arg = requester.args[1]; if (arg instanceof FileLoadOperation) { FileLoadOperation operation = (FileLoadOperation) requester.args[1]; - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject; - if (newStoryItem == null) { - TLRPC.TL_updateStory story = new TLRPC.TL_updateStory(); - story.user_id = storyItem.dialogId; - story.story = new TLRPC.TL_storyItemDeleted(); - story.story.id = storyItem.id; - ArrayList updates = new ArrayList<>(); - updates.add(story); - getMessagesController().processUpdateArray(updates, null, null, false, 0); - } else { - TLRPC.User user = getMessagesController().getUser(storyItem.dialogId); - if (user != null && user.contact) { - MessagesController.getInstance(currentAccount).getStoriesController().getStoriesStorage().updateStoryItem(storyItem.dialogId, newStoryItem); + if (operation.parentObject instanceof TLRPC.StoryItem) { + TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject; + if (newStoryItem == null) { + TLRPC.TL_updateStory story = new TLRPC.TL_updateStory(); + story.user_id = storyItem.dialogId; + story.story = new TLRPC.TL_storyItemDeleted(); + story.story.id = storyItem.id; + ArrayList updates = new ArrayList<>(); + updates.add(story); + getMessagesController().processUpdateArray(updates, null, null, false, 0); + } else { + TLRPC.User user = getMessagesController().getUser(storyItem.dialogId); + if (user != null && user.contact) { + MessagesController.getInstance(currentAccount).getStoriesController().getStoriesStorage().updateStoryItem(storyItem.dialogId, newStoryItem); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index eb4f2c39b..61ea8111d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -24,6 +24,7 @@ import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; @@ -141,8 +142,16 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO countDownLatch = null; } } - if (file == null) { - currentFile = loadOperation.getCurrentFile(); + File currentFileFast = loadOperation.getCurrentFileFast(); + if (file == null || !Objects.equals(currentFile, currentFileFast)) { + if (file != null) { + try { + file.close(); + } catch (Exception ignore) { + + } + } + currentFile = currentFileFast; if (currentFile != null) { try { file = new RandomAccessFile(currentFile, "r"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 16acfb1ed..6a8df8621 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -52,6 +52,7 @@ 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; @@ -171,6 +172,10 @@ public class ImageLoader { return null; } + public static boolean isSdCardPath(File videoFile) { + return !TextUtils.isEmpty(SharedConfig.storageCacheDir) && videoFile.getAbsolutePath().startsWith(SharedConfig.storageCacheDir); + } + public void moveToFront(String key) { if (key == null) { return; @@ -3291,6 +3296,9 @@ public class ImageLoader { } public void loadImageForImageReceiver(ImageReceiver imageReceiver) { + loadImageForImageReceiver(imageReceiver, null); + } + public void loadImageForImageReceiver(ImageReceiver imageReceiver, List preloadReceiver) { if (imageReceiver == null) { return; } @@ -3300,24 +3308,26 @@ public class ImageLoader { int guid = imageReceiver.getNewGuid(); if (mediaKey != null) { ImageLocation mediaLocation = imageReceiver.getMediaLocation(); - Drawable drawable; - if (useLottieMemCache(mediaLocation, mediaKey)) { - drawable = getFromLottieCache(mediaKey); - } else { - drawable = memCache.get(mediaKey); - if (drawable != null) { - memCache.moveToFront(mediaKey); - } - if (drawable == null) { - drawable = smallImagesMemCache.get(mediaKey); + Drawable drawable = findInPreloadImageReceivers(mediaKey, preloadReceiver); + if (drawable == null) { + if (useLottieMemCache(mediaLocation, mediaKey)) { + drawable = getFromLottieCache(mediaKey); + } else { + drawable = memCache.get(mediaKey); if (drawable != null) { - smallImagesMemCache.moveToFront(mediaKey); + memCache.moveToFront(mediaKey); } - } - if (drawable == null) { - drawable = wallpaperMemCache.get(mediaKey); - if (drawable != null) { - wallpaperMemCache.moveToFront(mediaKey); + if (drawable == null) { + drawable = smallImagesMemCache.get(mediaKey); + if (drawable != null) { + smallImagesMemCache.moveToFront(mediaKey); + } + } + if (drawable == null) { + drawable = wallpaperMemCache.get(mediaKey); + if (drawable != null) { + wallpaperMemCache.moveToFront(mediaKey); + } } } } @@ -3342,8 +3352,8 @@ public class ImageLoader { String imageKey = imageReceiver.getImageKey(); if (!imageSet && imageKey != null) { ImageLocation imageLocation = imageReceiver.getImageLocation(); - Drawable drawable = null; - if (useLottieMemCache(imageLocation, imageKey)) { + Drawable drawable = findInPreloadImageReceivers(imageKey, preloadReceiver); + if (drawable == null && useLottieMemCache(imageLocation, imageKey)) { drawable = getFromLottieCache(imageKey); } if (drawable == null) { @@ -3599,6 +3609,22 @@ public class ImageLoader { } } + private Drawable findInPreloadImageReceivers(String imageKey, List receivers) { + if (receivers == null) { + return null; + } + for (int i = 0; i < receivers.size(); i++) { + ImageReceiver receiver = receivers.get(i); + if (imageKey.equals(receiver.getImageKey())) { + return receiver.getImageDrawable(); + } + if (imageKey.equals(receiver.getMediaKey())) { + return receiver.getMediaDrawable(); + } + } + return null; + } + private BitmapDrawable getFromLottieCache(String imageKey) { BitmapDrawable drawable = lottieMemCache.get(imageKey); if (drawable instanceof AnimatedFileDrawable) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index c96f224ba..7c0ffe9e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -43,9 +43,12 @@ import org.telegram.ui.Components.RecyclableDrawable; import org.telegram.ui.Components.VectorAvatarThumbDrawable; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { + List preloadReceivers; public boolean updateThumbShaderMatrix() { if (currentThumbDrawable != null && thumbShader != null) { drawDrawable(null, currentThumbDrawable, 255, thumbShader, 0, 0, 0, null); @@ -58,6 +61,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return false; } + public void setPreloadingReceivers(List preloadReceivers) { + this.preloadReceivers = preloadReceivers; + } + + public Drawable getImageDrawable() { + return currentImageDrawable; + } + + public Drawable getMediaDrawable() { + return currentMediaDrawable; + } + public interface ImageReceiverDelegate { void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, boolean memCache); @@ -706,7 +721,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } private void loadImage() { - ImageLoader.getInstance().loadImageForImageReceiver(this); + ImageLoader.getInstance().loadImageForImageReceiver(this, preloadReceivers); invalidate(); } @@ -1047,6 +1062,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (setImageBackup != null && setImageBackup.isSet()) { SetImageBackup temp = setImageBackup; setImageBackup = null; + if (temp.thumb instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) temp.thumb; + if (!(bitmapDrawable instanceof RLottieDrawable) && !(bitmapDrawable instanceof AnimatedFileDrawable) && bitmapDrawable.getBitmap() != null && bitmapDrawable.getBitmap().isRecycled()) { + temp.thumb = null; + } + } setImage(temp.mediaLocation, temp.mediaFilter, temp.imageLocation, temp.imageFilter, temp.thumbLocation, temp.thumbFilter, temp.thumb, temp.size, temp.ext, temp.parentObject, temp.cacheType); temp.clear(); setImageBackup = temp; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 53812769a..59c754526 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -17508,7 +17508,10 @@ public class MessagesController extends BaseController implements NotificationCe reason = getRestrictionReason(user.restriction_reason); if (type != 3 && user.bot) { type = 1; - closeLast = true; + BaseFragment lastFragment = LaunchActivity.getLastFragment(); + if (!(lastFragment.storyViewer != null && lastFragment.storyViewer.isShown())) { + closeLast = true; + } } } if (reason != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index dcc4fe93f..dc76ec6f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -22,8 +22,6 @@ import android.util.SparseIntArray; import androidx.annotation.UiThread; import androidx.collection.LongSparseArray; -import com.google.android.exoplayer2.util.Log; - import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 811faa648..99c71bc3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -3708,7 +3708,11 @@ public class NotificationsController extends BaseController { } else if (names.isEmpty()) { msg.message = ""; } else if (names.size() == 1) { - msg.message = LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0)); + if (storiesCount == 1) { + msg.message = LocaleController.getString("StoryNotificationSingle"); + } else { + msg.message = LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0)); + } } else if (names.size() == 2) { msg.message = LocaleController.formatString(R.string.StoryNotification2, names.get(0), names.get(1)); } else if (names.size() == 3 && storyPushMessages.size() == 3) { @@ -4682,7 +4686,11 @@ public class NotificationsController extends BaseController { } else if (names.isEmpty()) { continue; } else if (names.size() == 1) { - text.append(LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0))); + if (storiesCount == 1) { + text.append(LocaleController.getString("StoryNotificationSingle")); + } else { + text.append(LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0))); + } } else if (names.size() == 2) { text.append(LocaleController.formatString(R.string.StoryNotification2, names.get(0), names.get(1))); } else if (names.size() == 3 && storyPushMessages.size() == 3) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index fb11cdfba..f8250d34e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -459,7 +459,7 @@ public class PushListenerController { } else { switch (loc_key) { case "STORY_NOTEXT": { - messageText = LocaleController.formatPluralString("StoryNotification1", 1, args[0]); + messageText = LocaleController.getString("StoryNotificationSingle"); message1 = null; msg_id = story_id; break; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/RuntimeClassNameTypeAdapterFactory.java b/TMessagesProj/src/main/java/org/telegram/messenger/RuntimeClassNameTypeAdapterFactory.java index 26aaad61c..9586f9dce 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/RuntimeClassNameTypeAdapterFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/RuntimeClassNameTypeAdapterFactory.java @@ -1,5 +1,6 @@ package org.telegram.messenger; +import com.google.gson.ExclusionStrategy; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -114,21 +115,23 @@ public final class RuntimeClassNameTypeAdapterFactory implements TypeAdapterF private final String typeFieldName; private final Map> labelToSubtype = new LinkedHashMap>(); private final Map, String> subtypeToLabel = new LinkedHashMap, String>(); + private final ExclusionStrategy exclusionStrategy; - private RuntimeClassNameTypeAdapterFactory(Class baseType, String typeFieldName) { + private RuntimeClassNameTypeAdapterFactory(Class baseType, String typeFieldName, ExclusionStrategy exclusionStrategy) { if (typeFieldName == null || baseType == null) { throw new NullPointerException(); } this.baseType = baseType; this.typeFieldName = typeFieldName; + this.exclusionStrategy = exclusionStrategy; } /** * Creates a new runtime type adapter using for {@code baseType} using {@code * typeFieldName} as the type field name. Type field names are case sensitive. */ - public static RuntimeClassNameTypeAdapterFactory of(Class baseType, String typeFieldName) { - return new RuntimeClassNameTypeAdapterFactory(baseType, typeFieldName); + public static RuntimeClassNameTypeAdapterFactory of(Class baseType, String typeFieldName, ExclusionStrategy exclusionStrategy) { + return new RuntimeClassNameTypeAdapterFactory(baseType, typeFieldName, exclusionStrategy); } /** @@ -136,7 +139,7 @@ public final class RuntimeClassNameTypeAdapterFactory implements TypeAdapterF * the type field name. */ public static RuntimeClassNameTypeAdapterFactory of(Class baseType) { - return new RuntimeClassNameTypeAdapterFactory(baseType, "class"); + return new RuntimeClassNameTypeAdapterFactory(baseType, "class", null); } /** @@ -171,6 +174,9 @@ public final class RuntimeClassNameTypeAdapterFactory implements TypeAdapterF public TypeAdapter create(Gson gson, TypeToken type) { + if (exclusionStrategy.shouldSkipClass(type.getRawType().getClass())) { + return null; + } final Map> labelToDelegate = new LinkedHashMap>(); final Map, TypeAdapter> subtypeToDelegate diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java index 81cedd763..8ef743501 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -436,6 +436,7 @@ public class CameraController implements MediaRecorder.OnInfoListener { if (!ignoreOrientation && orientation != -1) { matrix.setRotate(orientation); } + orientation = 0; matrix.postScale(-1, 1); Bitmap scaled = Bitmaps.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); if (scaled != bitmap) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java index 94f78328a..b584e60e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -60,9 +60,11 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import com.google.zxing.common.detector.MathUtils; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; @@ -77,6 +79,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieDrawable; import java.io.File; +import java.io.IOException; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -96,6 +99,8 @@ import javax.microedition.khronos.opengles.GL; @SuppressLint("NewApi") public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView { + public boolean WRITE_TO_FILE_IN_BACKGROUND = true; + public boolean isStory; private Size[] previewSize = new Size[2]; private Size[] pictureSize = new Size[2]; @@ -272,7 +277,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur addToDualWait(400L); return; } - if (!isFrontface && "samsung".equalsIgnoreCase(Build.MANUFACTURER) && !toggledDualAsSave) { + if (!isFrontface && "samsung".equalsIgnoreCase(Build.MANUFACTURER) && !toggledDualAsSave && cameraSession[0] != null) { final Handler handler = cameraThread.getHandler(); if (handler != null) { cameraThread.sendMessage(handler.obtainMessage(cameraThread.BLUR_CAMERA1), 0); @@ -1042,7 +1047,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private CameraSession currentSession[] = new CameraSession[2]; - private SurfaceTexture[] cameraSurface = new SurfaceTexture[2]; + private final SurfaceTexture[] cameraSurface = new SurfaceTexture[2]; private final int DO_RENDER_MESSAGE = 0; private final int DO_SHUTDOWN_MESSAGE = 1; @@ -1329,11 +1334,13 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur } public void finish() { - for (int i = 0; i < 2; ++i) { - if (cameraSurface[i] != null) { - cameraSurface[i].setOnFrameAvailableListener(null); - cameraSurface[i].release(); - cameraSurface[i] = null; + if (cameraSurface != null) { + for (int i = 0; i < cameraSurface.length; ++i) { + if (cameraSurface[i] != null) { + cameraSurface[i].setOnFrameAvailableListener(null); + cameraSurface[i].release(); + cameraSurface[i] = null; + } } } if (eglSurface != null) { @@ -1464,7 +1471,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur continue; } final int i = a < 0 ? 1 : a; - if (cameraSurface[i] == null || i != 0 && (currentSession[i] == null || !currentSession[i].isInitied()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) { + if (cameraSurface[i] == null) { + continue; + } + if (i != 0 && (currentSession[i] == null || !currentSession[i].isInitied()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) { continue; } @@ -1489,7 +1499,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur GLES20.glUniformMatrix4fv(vertexMatrixHandle, 1, false, mMVPMatrix[i], 0); if (i == 0) { GLES20.glUniform2f(pixelHandle, pixelW, pixelH); - GLES20.glUniform1f(dualHandle, 0f); + GLES20.glUniform1f(dualHandle, dual ? 1 : 0); } else { GLES20.glUniform2f(pixelHandle, pixelDualW, pixelDualH); GLES20.glUniform1f(dualHandle, 1f); @@ -1947,6 +1957,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private static final int IFRAME_INTERVAL = 1; private File videoFile; + private File fileToWrite; + private boolean writingToDifferentFile; private int videoBitrate; private boolean videoConvertFirstWrite = true; private boolean blendEnabled; @@ -2348,7 +2360,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur GLES20.glEnable(GLES20.GL_BLEND); blendEnabled = true; } - if (dual) { + final boolean isDual = dual; + if (isDual) { GLES20.glClearColor(0.f, 0.f, 0.f, 1.f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); } @@ -2379,7 +2392,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur GLES20.glUniform1f(blurHandle, 0); if (i == 0) { GLES20.glUniform2f(pixelHandle, pixelW, pixelH); - GLES20.glUniform1f(dualHandle, 0f); + GLES20.glUniform1f(dualHandle, isDual ? 1f : 0f); } else { GLES20.glUniform2f(pixelHandle, pixelDualW, pixelDualH); GLES20.glUniform1f(dualHandle, 1f); @@ -2484,6 +2497,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur e.printStackTrace(); } + if (writingToDifferentFile) { + if (!fileToWrite.renameTo(videoFile)) { + FileLog.e("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"); + } + } + } + EGL14.eglDestroySurface(eglDisplay, eglSurface); eglSurface = EGL14.EGL_NO_SURFACE; if (surface != null) { @@ -2586,8 +2612,24 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur surface = videoEncoder.createInputSurface(); videoEncoder.start(); + boolean isSdCard = ImageLoader.isSdCardPath(videoFile); + fileToWrite = videoFile; + if (isSdCard) { + try { + fileToWrite = new File(ApplicationLoader.getFilesDirFixed(), "camera_tmp.mp4"); + if (fileToWrite.exists()) { + fileToWrite.delete(); + } + writingToDifferentFile = true; + } catch (Throwable e) { + FileLog.e(e); + fileToWrite = videoFile; + writingToDifferentFile = false; + } + } + Mp4Movie movie = new Mp4Movie(); - movie.setCacheFile(videoFile); + movie.setCacheFile(fileToWrite); movie.setRotation(0); movie.setSize(videoWidth, videoHeight); mediaMuxer = new MP4Builder().createMovie(movie, false, false); @@ -2749,7 +2791,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur if (encodedData == null) { throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null"); } - boolean allowReleaseBuffer = true; if (videoBufferInfo.size > 1) { if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { if (prependHeaderSize != 0 && (videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) { @@ -2765,18 +2806,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur bufferInfo.offset = videoBufferInfo.offset; bufferInfo.flags = videoBufferInfo.flags; bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs; - allowReleaseBuffer = false; + ByteBuffer byteBuffer = encodedData.duplicate(); fileWriteQueue.postRunnable(() -> { try { - mediaMuxer.writeSampleData(videoTrackIndex, encodedData, bufferInfo, true); - MediaCodec videoEncoder = VideoRecorder.this.videoEncoder; - if (videoEncoder != null) { - try { - videoEncoder.releaseOutputBuffer(encoderStatus, false); - } catch (Throwable e) { - //ignore IllegalStateException if codec released - } - } + mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo, true); } catch (Exception e) { FileLog.e(e); } @@ -2813,9 +2846,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur videoTrackIndex = mediaMuxer.addTrack(newFormat, false); } } - if (allowReleaseBuffer) { - videoEncoder.releaseOutputBuffer(encoderStatus, false); - } + videoEncoder.releaseOutputBuffer(encoderStatus, false); if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { break; } @@ -2860,24 +2891,16 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur bufferInfo.offset = audioBufferInfo.offset; bufferInfo.flags = audioBufferInfo.flags; bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs; + ByteBuffer byteBuffer = encodedData.duplicate(); fileWriteQueue.postRunnable(() -> { try { - mediaMuxer.writeSampleData(audioTrackIndex, encodedData, bufferInfo, false); - MediaCodec audioEncoder = VideoRecorder.this.audioEncoder; - if (audioEncoder != null) { - try { - audioEncoder.releaseOutputBuffer(encoderStatus, false); - } catch (Throwable e) { - //ignore IllegalStateException if codec released - } - } + mediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, bufferInfo, false); } catch (Exception e) { FileLog.e(e); } }); - } else { - audioEncoder.releaseOutputBuffer(encoderStatus, false); } + audioEncoder.releaseOutputBuffer(encoderStatus, false); if ((audioBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 94821564a..377ba1e51 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -760,6 +760,7 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F parent.removeViewInLayout(lastFragment.actionBar); } } + lastFragment.detachStoryViewer(); } layoutToIgnore = null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 77c75aeb3..faa83afb4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -16,6 +16,7 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; @@ -166,6 +167,12 @@ public class ActionBarPopupWindow extends PopupWindow { try { scrollView = new ScrollView(context); + scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { + @Override + public void onScrollChanged() { + invalidate(); + } + }); scrollView.setVerticalScrollBarEnabled(false); if (swipeBackLayout != null) { swipeBackLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, shownFromBottom ? Gravity.BOTTOM : Gravity.TOP)); @@ -416,6 +423,8 @@ public class ActionBarPopupWindow extends PopupWindow { return super.dispatchKeyEvent(event); } + Path path; + @Override protected void dispatchDraw(Canvas canvas) { if (swipeBackGravityRight) { @@ -487,9 +496,15 @@ public class ActionBarPopupWindow extends PopupWindow { backgroundDrawable.draw(canvas); if (hasGap) { canvas.save(); - AndroidUtilities.rectTmp2.set(backgroundDrawable.getBounds()); - AndroidUtilities.rectTmp2.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8)); - canvas.clipRect(AndroidUtilities.rectTmp2); + AndroidUtilities.rectTmp.set(backgroundDrawable.getBounds()); + AndroidUtilities.rectTmp.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + if (path == null) { + path = new Path(); + } else { + path.rewind(); + } + path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), Path.Direction.CW); + canvas.clipPath(path); for (int i = 0; i < linearLayout.getChildCount(); i++) { if (linearLayout.getChildAt(i) instanceof GapView && linearLayout.getChildAt(i).getVisibility() == View.VISIBLE) { canvas.save(); @@ -504,7 +519,7 @@ public class ActionBarPopupWindow extends PopupWindow { break; } } - canvas.translate(x, y * scrollView.getScaleY()); + canvas.translate(x, y * scrollView.getScaleY() - scrollView.getScrollY()); child.draw(canvas); canvas.restore(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index a106030b8..cbbd484d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -84,26 +84,13 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { } public void setStories(ArrayList stories, boolean animated) { - boolean hasStories = !stories.isEmpty(); - userStories.clear(); - userStories.addAll(stories); - if (this.hasStories != hasStories) { - this.hasStories = hasStories; -// if (!animated) { -// notifyDataSetChanged(); -// } else { -// cleanupCache(); -// notifyDataSetChanged(); -// if (hasStories) { -// notifyItemInserted(0); -// } else { -// notifyItemRemoved(0); -// notifyItemRangeChanged(1, getItemCount()); -// } -// } - } - update(true); - // notifyDataSetChanged(); +// boolean hasStories = !stories.isEmpty(); +// userStories.clear(); +// userStories.addAll(stories); +// if (this.hasStories != hasStories) { +// this.hasStories = hasStories; +// } +// update(true); } public void setDisableSections(boolean value) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index 4ebc057f8..1a897adb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -74,6 +74,7 @@ import org.telegram.ui.Components.PullForegroundDrawable; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.DialogsActivity; import org.telegram.ui.Stories.DialogStoriesCell; +import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoriesUtilities; @@ -92,8 +93,8 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements VIEW_TYPE_USER = 6, VIEW_TYPE_HEADER = 7, VIEW_TYPE_SHADOW = 8, -// VIEW_TYPE_ARCHIVE = 9, - VIEW_TYPE_LAST_EMPTY = 10, + // VIEW_TYPE_ARCHIVE = 9, + VIEW_TYPE_LAST_EMPTY = 10, VIEW_TYPE_NEW_CHAT_HINT = 11, VIEW_TYPE_TEXT = 12, VIEW_TYPE_CONTACTS_FLICKER = 13, @@ -487,7 +488,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements if (view != null) { float offset = view.getTop() - recyclerListView.getPaddingTop(); if (!hasStories) { - // offset += tabsTranslation; + // offset += tabsTranslation; } else { tabsTranslation = 0; } @@ -660,8 +661,8 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements case VIEW_TYPE_ARCHIVE_FULLSCREEN: LastEmptyView lastEmptyView = new LastEmptyView(mContext); lastEmptyView.addView( - new ArchiveHelp(mContext, currentAccount, null, DialogsAdapter.this::onArchiveSettingsClick,null), - LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, -(int) (DialogStoriesCell.HEIGHT_IN_DP * .5f), 0, 0) + new ArchiveHelp(mContext, currentAccount, null, DialogsAdapter.this::onArchiveSettingsClick, null), + LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, -(int) (DialogStoriesCell.HEIGHT_IN_DP * .5f), 0, 0) ); view = lastEmptyView; break; @@ -733,6 +734,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements if (dialogsType == DialogsActivity.DIALOGS_TYPE_BOT_REQUEST_PEER) { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } + break; } case VIEW_TYPE_STORIES: { view = new View(mContext) { @@ -1091,6 +1093,23 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements parentFragment.showChatPreview(cell); } + @Override + public void openHiddenStories() { + StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); + if (storiesController.getHiddenList().isEmpty()) { + return; + } + boolean unreadOnly = storiesController.getUnreadState(storiesController.getHiddenList().get(0).user_id) != StoriesController.STATE_READ; + ArrayList peerIds = new ArrayList<>(); + for (int i = 0; i < storiesController.getHiddenList().size(); i++) { + if (!unreadOnly || storiesController.getUnreadState(storiesController.getHiddenList().get(i).user_id) != StoriesController.STATE_READ) { + peerIds.add(storiesController.getHiddenList().get(i).user_id); + } + } + + parentFragment.getOrCreateStoryViewer().open(mContext, null, peerIds, 0, null, null, StoriesListPlaceProvider.of(recyclerListView, true), false); + } + public void setIsTransitionSupport() { this.isTransitionSupport = true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index 164ca532d..2527da4eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -316,12 +316,12 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { items.add(new Item(15, LocaleController.getString("SetEmojiStatus", R.string.SetEmojiStatus), R.drawable.msg_status_set)); } } -// if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { + if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories)); items.add(null); // divider -// } else if (me != null && me.isPremium()) { -// items.add(null); // divider -// } + } else if (me != null && me.isPremium()) { + items.add(null); // divider + } items.add(new Item(2, LocaleController.getString("NewGroup", R.string.NewGroup), newGroupIcon)); //items.add(new Item(3, LocaleController.getString("NewSecretChat", R.string.NewSecretChat), newSecretIcon)); //items.add(new Item(4, LocaleController.getString("NewChannel", R.string.NewChannel), newChannelIcon)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java index b825d9976..37052c5c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java @@ -112,7 +112,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown try { CharSequence author = currentMessageObject.getMusicAuthor().replace('\n', ' '); if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject)); + author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject, 2)); } CharSequence authorFinal = TextUtils.ellipsize(author, Theme.chat_contextResult_descriptionTextPaint, maxWidth, TextUtils.TruncateAt.END); descriptionLayout = new StaticLayout(authorFinal, Theme.chat_contextResult_descriptionTextPaint, maxWidth + AndroidUtilities.dp(4), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 3fdc81eef..d0c525054 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -1063,7 +1063,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD private int getImageSize(MessageObject messageObject) { int imageSize = stickerSize; if (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || isNewStyleButtonLayout()) { - imageSize = (int) (stickerSize * 0.7f); + imageSize = AndroidUtilities.dp(78);//Math.max(, (int) (stickerSize * 0.7f)); } return imageSize; } @@ -1178,7 +1178,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD } else { giftPremiumTitleLayout = null; } - if (currentMessageObject != null && (currentMessageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || currentMessageObject.isStoryMention())) { + if (currentMessageObject != null && isNewStyleButtonLayout()) { giftSubtitlePaint.setTextSize(AndroidUtilities.dp(13)); } else { giftSubtitlePaint.setTextSize(AndroidUtilities.dp(15)); 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 c6ad4b501..40d949bf5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -4894,6 +4894,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate type = webpage == null ? null : webpage.type; duration = storyItem != null && storyItem.media != null && storyItem.media.document != null ? (int) MessageObject.getDocumentDuration(storyItem.media.document) : 0; smallImage = false; + isSmallImage = false; } else if (hasLinkPreview) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) webpage; site_name = webPage.site_name; 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 33be39bf5..c6c0a8ff6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -161,16 +161,26 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private TimerDrawable timerDrawable; private Paint timerPaint; private Paint timerPaint2; - public final StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(false) { + public final StoriesUtilities.AvatarStoryParams storyParams = new StoriesUtilities.AvatarStoryParams(false) { @Override public void openStory(long dialogId, Runnable onDone) { - if (delegate != null) { - delegate.openStory(DialogCell.this, onDone); + if (delegate == null) { + return; + } + if (currentDialogFolderId != 0) { + delegate.openHiddenStories(); + } else { + if (delegate != null) { + delegate.openStory(DialogCell.this, onDone); + } } } @Override public void onLongPress() { + if (delegate == null) { + return; + } delegate.showChatPreview(DialogCell.this); } }; @@ -522,7 +532,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava public DialogCell(DialogsActivity fragment, Context context, boolean needCheck, boolean forceThreeLines, int account, Theme.ResourcesProvider resourcesProvider) { super(context); - params.allowLongress = true; + storyParams.allowLongress = true; this.resourcesProvider = resourcesProvider; parentFragment = fragment; Theme.createDialogsResources(context); @@ -697,7 +707,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava AnimatedEmojiSpan.release(this, animatedEmojiStack2); AnimatedEmojiSpan.release(this, animatedEmojiStack3); AnimatedEmojiSpan.release(this, animatedEmojiStackName); - params.onDetachFromWindow(); + storyParams.onDetachFromWindow(); } @Override @@ -1888,7 +1898,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava avatarLeft = AndroidUtilities.dp(10); thumbLeft = avatarLeft + AndroidUtilities.dp(56 + 13); } - params.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(56), avatarTop + AndroidUtilities.dp(56)); + storyParams.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(56), avatarTop + AndroidUtilities.dp(56)); for (int i = 0; i < thumbImage.length; ++i) { thumbImage[i].setImageCoords(thumbLeft + (thumbSize + 2) * i, avatarTop + AndroidUtilities.dp(31) + (twoLinesForName ? AndroidUtilities.dp(20) : 0), AndroidUtilities.dp(18), AndroidUtilities.dp(18)); } @@ -1911,7 +1921,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava avatarLeft = AndroidUtilities.dp(10); thumbLeft = avatarLeft + AndroidUtilities.dp(56 + 11); } - params.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(54), avatarTop + AndroidUtilities.dp(54)); + storyParams.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(54), avatarTop + AndroidUtilities.dp(54)); for (int i = 0; i < thumbImage.length; ++i) { thumbImage[i].setImageCoords(thumbLeft + (thumbSize + 2) * i, avatarTop + AndroidUtilities.dp(30) + (twoLinesForName ? AndroidUtilities.dp(20) : 0), AndroidUtilities.dp(thumbSize), AndroidUtilities.dp(thumbSize)); } @@ -3793,8 +3803,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava canvas.scale(scale, scale, avatarImage.getCenterX(), avatarImage.getCenterY()); } - if (drawAvatar && (!(currentDialogFolderId != 0 || isTopic && forumTopic != null && forumTopic.id == 1) || archivedChatsDrawable == null || !archivedChatsDrawable.isDraw())) { - StoriesUtilities.drawAvatarWithStory(currentDialogId, canvas, avatarImage, params); + if (drawAvatar && (!(isTopic && forumTopic != null && forumTopic.id == 1) || archivedChatsDrawable == null || !archivedChatsDrawable.isDraw())) { + storyParams.drawHiddenStoriesAsSegments = currentDialogFolderId != 0; + StoriesUtilities.drawAvatarWithStory(currentDialogId, canvas, avatarImage, storyParams); } if (animatingArchiveAvatar) { @@ -3812,8 +3823,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } else { drawCounterMuted = chat != null && chat.forum && forumTopic == null ? !hasUnmutedTopics : dialogMuted; } - int countLeftLocal = (int) (params.originalAvatarRect.left + avatarImage.getImageWidth() - countWidth - AndroidUtilities.dp(5f)); - int countLeftOld = (int) (params.originalAvatarRect.left + avatarImage.getImageWidth() - countWidthOld - AndroidUtilities.dp(5f)); + int countLeftLocal = (int) (storyParams.originalAvatarRect.left + avatarImage.getImageWidth() - countWidth - AndroidUtilities.dp(5f)); + int countLeftOld = (int) (storyParams.originalAvatarRect.left + avatarImage.getImageWidth() - countWidthOld - AndroidUtilities.dp(5f)); int countTop = (int) (avatarImage.getImageY() + avatarImage.getImageHeight() - AndroidUtilities.dp(22)); drawCounter(canvas, drawCounterMuted, countTop, countLeftLocal, countLeftOld, rightFragmentOpenedProgress, true); } @@ -3970,9 +3981,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava int top = (int) (avatarImage.getImageY2() - AndroidUtilities.dp(9)); int left; if (LocaleController.isRTL) { - left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(9)); + left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(9)); } else { - left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(9)); + left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(9)); } timerDrawable.setBounds( 0, 0, AndroidUtilities.dp(22), AndroidUtilities.dp(22) @@ -4011,12 +4022,12 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (user != null && !MessagesController.isSupportUser(user) && !user.bot) { boolean isOnline = isOnline(); if (isOnline || onlineProgress != 0) { - int top = (int) (params.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8)); + int top = (int) (storyParams.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8)); int left; if (LocaleController.isRTL) { - left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); + left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); } else { - left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); + left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); } Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); @@ -4045,12 +4056,12 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava hasCall = chat.call_active && chat.call_not_empty; if ((hasCall || chatCallProgress != 0) && rightFragmentOpenedProgress < 1f) { float checkProgress = checkBox != null && checkBox.isChecked() ? 1.0f - checkBox.getProgress() : 1.0f; - int top = (int) (params.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8)); + int top = (int) (storyParams.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8)); int left; if (LocaleController.isRTL) { - left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); + left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); } else { - left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); + left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6)); } if (rightFragmentOpenedProgress != 0) { @@ -4370,9 +4381,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava archivedChatsDrawable.outRadius = 0; archivedChatsDrawable.outImageSize = 0; } else { - archivedChatsDrawable.outCy = params.originalAvatarRect.centerY(); - archivedChatsDrawable.outCx = params.originalAvatarRect.centerX(); - archivedChatsDrawable.outRadius = params.originalAvatarRect.width() / 2.0f; + archivedChatsDrawable.outCy = storyParams.originalAvatarRect.centerY(); + archivedChatsDrawable.outCx = storyParams.originalAvatarRect.centerX(); + archivedChatsDrawable.outRadius = avatarImage.getImageWidth() / 2.0f; archivedChatsDrawable.outImageSize = avatarImage.getBitmapWidth(); } archivedChatsDrawable.startOutAnimation(); @@ -4864,7 +4875,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (rightFragmentOpenedProgress == 0 && params.checkOnTouchEvent(ev, this)) { + if (rightFragmentOpenedProgress == 0 && storyParams.checkOnTouchEvent(ev, this)) { return true; } return super.onInterceptTouchEvent(ev); @@ -4873,14 +4884,14 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { - params.checkOnTouchEvent(ev, this); + storyParams.checkOnTouchEvent(ev, this); } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { - if (rightFragmentOpenedProgress == 0 && params.checkOnTouchEvent(event, this)) { + if (rightFragmentOpenedProgress == 0 && storyParams.checkOnTouchEvent(event, this)) { return true; } if (delegate == null || delegate.canClickButtonInside()) { @@ -4935,6 +4946,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava boolean canClickButtonInside(); void openStory(DialogCell dialogCell, Runnable onDone); void showChatPreview(DialogCell dialogCell); + void openHiddenStories(); } private class DialogUpdateHelper { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index 3c64b0281..98b945faf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -31,7 +31,6 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; @@ -65,6 +64,7 @@ import org.telegram.ui.Components.Premium.StarParticlesView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.Reactions.AnimatedEmojiEffect; +import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.SnowflakesEffect; import org.telegram.ui.ThemeActivity; @@ -125,6 +125,38 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter animatedStatus.translate(AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); } } + + @Override + public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } + + @Override + public void invalidateDrawable(Drawable who) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidateDrawable(who); + } + + @Override + public void invalidate(Rect dirty) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(dirty); + } }; nameTextView.setRightDrawableOnClick(e -> { if (lastUser != null && lastUser.premium) { @@ -441,6 +473,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + status.attach(); updateColors(); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ @@ -451,6 +484,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + status.detach(); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java index 120e1c095..a50ffbd07 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java @@ -88,6 +88,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No protected void onAttachedToWindow() { super.onAttachedToWindow(); textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText)); + status.attach(); for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.updateInterfaces); @@ -98,6 +99,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + status.detach(); for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.updateInterfaces); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java index 5e7c33c22..3e73f3a8a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java @@ -168,7 +168,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F try { CharSequence title; if (viewType == VIEW_TYPE_GLOBAL_SEARCH && (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo())) { - title = FilteredSearchView.createFromInfoString(currentMessageObject); + title = FilteredSearchView.createFromInfoString(currentMessageObject, 1); } else { title = currentMessageObject.getMusicTitle().replace('\n', ' '); } @@ -210,7 +210,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F author = authorH; } if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject)); + author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject, 1)); } TextPaint paint = viewType == VIEW_TYPE_GLOBAL_SEARCH ? description2TextPaint : Theme.chat_contextResult_descriptionTextPaint; author = TextUtils.ellipsize(author, paint, maxWidth, TextUtils.TruncateAt.END); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index f5221ca98..602b7e0b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -37,6 +37,7 @@ import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -220,6 +221,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle dateTextView.setSingleLine(true); dateTextView.setEllipsize(TextUtils.TruncateAt.END); dateTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + NotificationCenter.listenEmojiLoading(dateTextView); if (viewType == VIEW_TYPE_PICKER) { dateTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); addView(dateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 34, LocaleController.isRTL ? 72 : 8, 0)); @@ -509,7 +511,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle fileSize = String.format(Locale.ENGLISH, "%s / %s", AndroidUtilities.formatFileSize(downloadedSize), AndroidUtilities.formatFileSize(message.getDocument().size)); } if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - CharSequence fromName = FilteredSearchView.createFromInfoString(message); + CharSequence fromName = FilteredSearchView.createFromInfoString(message, true, 2, dateTextView.getPaint()); dateTextView.setText(new SpannableStringBuilder().append(fileSize) .append(' ').append(dotSpan).append(' ') diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 4419e65ee..b533cd353 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -477,7 +477,7 @@ public class SharedLinkCell extends FrameLayout { } if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - fromInfoLayout = ChatMessageCell.generateStaticLayout(FilteredSearchView.createFromInfoString(message), description2TextPaint, maxWidth, maxWidth, 0, desctiptionLines); + fromInfoLayout = ChatMessageCell.generateStaticLayout(FilteredSearchView.createFromInfoString(message, true, 2, description2TextPaint), description2TextPaint, maxWidth, maxWidth, 0, desctiptionLines); fromInfoLayoutEmojis = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, fromInfoLayoutEmojis, fromInfoLayout); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index 74b246da7..4eab56b0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -65,6 +65,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica private Theme.ResourcesProvider resourcesProvider; private AvatarDrawable avatarDrawable; + private boolean storiable; private Object currentObject; private TLRPC.EncryptedChat encryptedChat; @@ -142,8 +143,12 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica avatarImageView = new BackupImageView(context) { @Override protected void onDraw(Canvas canvas) { - storyParams.originalAvatarRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - StoriesUtilities.drawAvatarWithStory(dialogId, canvas, imageReceiver, storyParams); + if (storiable) { + storyParams.originalAvatarRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + StoriesUtilities.drawAvatarWithStory(dialogId, canvas, imageReceiver, storyParams); + } else { + super.onDraw(canvas); + } } @Override @@ -257,6 +262,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica if (object == null && name == null && status == null) { currentStatus = null; currentName = null; + storiable = false; currentObject = null; nameTextView.setText(""); statusTextView.setText(""); @@ -271,6 +277,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica } } catch (Exception ignore) {} currentName = name; + storiable = !(object instanceof String); currentObject = object; currentDrawable = resId; needDivider = divider; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index a5f7777ce..e95577fb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -23126,7 +23126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not primaryMessage = null; message = null; } - if (message == null || message.type == MessageObject.TYPE_STORY_MENTION) { + if (message == null) { return false; } if (!single && message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { @@ -23231,7 +23231,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { allowPin = false; } - allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory(); + allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION; boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards; boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())) && !message.isExpiredStory(); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId && message.type != MessageObject.TYPE_STORY; @@ -23645,7 +23645,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && (!selectedObject.needDrawBluredPreview() || selectedObject.hasExtendedMediaPreview()) && !selectedObject.isLiveLocation() && selectedObject.type != MessageObject.TYPE_PHONE_CALL && !noforwards && - selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() && !message.isExpiredStory()) { + selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() + && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(OPTION_FORWARD); icons.add(R.drawable.msg_forward); 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 bd22a4593..3f3e17149 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -34,6 +34,7 @@ import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LiteMode; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; @@ -41,7 +42,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Components.Premium.PremiumLockIconView; +import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.SelectAnimatedEmojiDialog; import java.io.File; @@ -146,6 +147,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private static HashMap fetchers; + public static EmojiDocumentFetcher getDocumentFetcher(int account) { if (fetchers == null) { fetchers = new HashMap<>(); @@ -156,17 +158,23 @@ public class AnimatedEmojiDrawable extends Drawable { } return fetcher; } + public static class EmojiDocumentFetcher { private HashMap emojiDocumentsCache; private HashMap> loadingDocuments; private HashSet toFetchDocuments; private Runnable fetchRunnable; + private Runnable uiDbCallback; private final int currentAccount; public EmojiDocumentFetcher(int account) { currentAccount = account; } + public void setUiDbCallback(Runnable uiDbCallback) { + this.uiDbCallback = uiDbCallback; + } + public void fetchDocument(long id, ReceivedDocument onDone) { synchronized (this) { if (emojiDocumentsCache != null) { @@ -204,7 +212,7 @@ public class AnimatedEmojiDrawable extends Drawable { AndroidUtilities.runOnUIThread(fetchRunnable = () -> { ArrayList emojiToLoad = new ArrayList<>(toFetchDocuments); toFetchDocuments.clear(); - loadFromDatabase(emojiToLoad); + loadFromDatabase(emojiToLoad, uiDbCallback == null); fetchRunnable = null; }); } @@ -219,51 +227,73 @@ public class AnimatedEmojiDrawable extends Drawable { return true; } + private void loadFromDatabase(ArrayList emojiToLoad, boolean async) { + if (async) { + MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount); + messagesStorage.getStorageQueue().postRunnable(() -> loadFromDatabase(emojiToLoad)); + } else { + loadFromDatabase(emojiToLoad); + } + } + private void loadFromDatabase(ArrayList emojiToLoad) { MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount); - messagesStorage.getStorageQueue().postRunnable(() -> { - SQLiteDatabase database = messagesStorage.getDatabase(); - if (database == null) { - return; - } - try { - String idsStr = TextUtils.join(",", emojiToLoad); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM animated_emoji WHERE document_id IN (%s)", idsStr)); - ArrayList documents = new ArrayList<>(); - HashSet loadFromServerIds = new HashSet<>(emojiToLoad); - while (cursor.next()) { - NativeByteBuffer byteBuffer = cursor.byteBufferValue(0); - try { - TLRPC.Document document = TLRPC.Document.TLdeserialize(byteBuffer, byteBuffer.readInt32(true), true); - if (document != null && document.id != 0) { - documents.add(document); - loadFromServerIds.remove(document.id); - } - } catch (Exception e) { - FileLog.e(e); - } - if (byteBuffer != null) { - byteBuffer.reuse(); + SQLiteDatabase database = messagesStorage.getDatabase(); + if (database == null) { + return; + } + try { + String idsStr = TextUtils.join(",", emojiToLoad); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM animated_emoji WHERE document_id IN (%s)", idsStr)); + ArrayList documents = new ArrayList<>(); + HashSet loadFromServerIds = new HashSet<>(emojiToLoad); + while (cursor.next()) { + NativeByteBuffer byteBuffer = cursor.byteBufferValue(0); + try { + TLRPC.Document document = TLRPC.Document.TLdeserialize(byteBuffer, byteBuffer.readInt32(true), true); + if (document != null && document.id != 0) { + documents.add(document); + loadFromServerIds.remove(document.id); } + } catch (Exception e) { + FileLog.e(e); + } + if (byteBuffer != null) { + byteBuffer.reuse(); } - - AndroidUtilities.runOnUIThread(() -> { - processDocuments(documents); - if (!loadFromServerIds.isEmpty()) { - loadFromServer(new ArrayList<>(loadFromServerIds)); - } - }); - cursor.dispose(); - } catch (SQLiteException e) { - messagesStorage.checkSQLException(e); } - }); + + processDatabaseResult(documents, loadFromServerIds); + cursor.dispose(); + + if (uiDbCallback != null) { + uiDbCallback.run(); + uiDbCallback = null; + } + } catch (SQLiteException e) { + messagesStorage.checkSQLException(e); + } + } + + private void processDocumentsAndLoadMore(ArrayList documents, HashSet loadFromServerIds) { + processDocuments(documents); + if (!loadFromServerIds.isEmpty()) { + loadFromServer(new ArrayList<>(loadFromServerIds)); + } + } + + private void processDatabaseResult(ArrayList documents, HashSet loadFromServerIds) { + if (Thread.currentThread() == Looper.getMainLooper().getThread()) { + processDocumentsAndLoadMore(documents, loadFromServerIds); + } else { + NotificationCenter.getInstance(currentAccount).doOnIdle(() -> AndroidUtilities.runOnUIThread(() -> processDocumentsAndLoadMore(documents, loadFromServerIds))); + } } private void loadFromServer(ArrayList loadFromServerIds) { final TLRPC.TL_messages_getCustomEmojiDocuments req = new TLRPC.TL_messages_getCustomEmojiDocuments(); req.document_id = loadFromServerIds; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> AndroidUtilities.runOnUIThread(() -> { HashSet loadedFromServer = new HashSet<>(loadFromServerIds); if (res instanceof TLRPC.Vector) { ArrayList objects = ((TLRPC.Vector) res).objects; @@ -280,7 +310,7 @@ public class AnimatedEmojiDrawable extends Drawable { loadFromServer(new ArrayList<>(loadedFromServer)); } } - })); + }))); } private void putToStorage(ArrayList objects) { @@ -438,11 +468,13 @@ public class AnimatedEmojiDrawable extends Drawable { sizedp = 34; } } + public long getDocumentId() { return this.document != null ? this.document.id : this.documentId; } private static boolean liteModeKeyboard, liteModeReactions; + private static void updateLiteModeValues() { liteModeKeyboard = LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD); liteModeReactions = LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); @@ -472,6 +504,7 @@ public class AnimatedEmojiDrawable extends Drawable { }; imageReceiver.setAllowLoadingOnAttachedOnly(true); }; + if (cacheType == CACHE_TYPE_RENDERING_VIDEO) { imageReceiver.ignoreNotifications = true; } @@ -541,7 +574,7 @@ public class AnimatedEmojiDrawable extends Drawable { if (onlyStaticPreview || (!liteModeKeyboard && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW)) { if ("video/webm".equals(document.mime_type)) { imageReceiver.setImage(null, null, ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1); - } else if (MessageObject.isAnimatedStickerDocument(document, true)){ + } else if (MessageObject.isAnimatedStickerDocument(document, true)) { imageReceiver.setImage(mediaLocation, mediaFilter + "_firstframe", null, null, thumbDrawable, document.size, null, document, 1); } else { imageReceiver.setImage(ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1); @@ -612,6 +645,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private static Paint placeholderPaint; + public static void updatePlaceholderPaintColor() { if (placeholderPaint != null) { placeholderPaint.setColor(Theme.isCurrentThemeDark() ? 0x0fffffff : 0x0f000000); @@ -706,6 +740,7 @@ public class AnimatedEmojiDrawable extends Drawable { public static int attachedCount = 0; public static ArrayList attachedDrawable; + private void updateAttachState() { if (imageReceiver == null) { return; @@ -742,6 +777,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private Boolean canOverrideColorCached = null; + public boolean canOverrideColor() { if (canOverrideColorCached != null) { return canOverrideColorCached; @@ -753,6 +789,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private Boolean isDefaultStatusEmojiCached = null; + public boolean isDefaultStatusEmoji() { if (isDefaultStatusEmojiCached != null) { return isDefaultStatusEmojiCached; @@ -760,8 +797,8 @@ public class AnimatedEmojiDrawable extends Drawable { if (document != null) { TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document); return isDefaultStatusEmojiCached = ( - set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses || - set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L) + set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses || + set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L) ); } return false; @@ -812,6 +849,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private static HashMap dominantColors; + public static int getDominantColor(AnimatedEmojiDrawable yourDrawable) { if (yourDrawable == null) { return 0; @@ -868,6 +906,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private int alpha = 255; + @Override public void setAlpha(int alpha) { this.alpha = alpha; @@ -945,6 +984,7 @@ public class AnimatedEmojiDrawable extends Drawable { private Integer lastColor; private ColorFilter colorFilter; + public void setColor(Integer color) { if (lastColor == null && color == null || lastColor != null && lastColor.equals(color)) { return; @@ -967,17 +1007,17 @@ public class AnimatedEmojiDrawable extends Drawable { drawables[1].setBounds(bounds); } else if (center) { drawables[1].setBounds( - bounds.centerX() - drawables[1].getIntrinsicWidth() / 2, - bounds.centerY() - drawables[1].getIntrinsicHeight() / 2, - bounds.centerX() + drawables[1].getIntrinsicWidth() / 2, - bounds.centerY() + drawables[1].getIntrinsicHeight() / 2 + bounds.centerX() - drawables[1].getIntrinsicWidth() / 2, + bounds.centerY() - drawables[1].getIntrinsicHeight() / 2, + bounds.centerX() + drawables[1].getIntrinsicWidth() / 2, + bounds.centerY() + drawables[1].getIntrinsicHeight() / 2 ); } else { // left drawables[1].setBounds( - bounds.left, - bounds.centerY() - drawables[1].getIntrinsicHeight() / 2, - bounds.left + drawables[1].getIntrinsicWidth(), - bounds.centerY() + drawables[1].getIntrinsicHeight() / 2 + bounds.left, + bounds.centerY() - drawables[1].getIntrinsicHeight() / 2, + bounds.left + drawables[1].getIntrinsicWidth(), + bounds.centerY() + drawables[1].getIntrinsicHeight() / 2 ); } drawables[1].setColorFilter(colorFilter); @@ -1001,10 +1041,10 @@ public class AnimatedEmojiDrawable extends Drawable { canvas.scale(scale, scale, bounds.centerX(), bounds.centerY()); } drawables[0].setBounds( - bounds.centerX() - drawables[0].getIntrinsicWidth() / 2, - bounds.centerY() - drawables[0].getIntrinsicHeight() / 2, - bounds.centerX() + drawables[0].getIntrinsicWidth() / 2, - bounds.centerY() + drawables[0].getIntrinsicHeight() / 2 + bounds.centerX() - drawables[0].getIntrinsicWidth() / 2, + bounds.centerY() - drawables[0].getIntrinsicHeight() / 2, + bounds.centerX() + drawables[0].getIntrinsicWidth() / 2, + bounds.centerY() + drawables[0].getIntrinsicHeight() / 2 ); } else { // left if (progress < 1) { @@ -1012,10 +1052,10 @@ public class AnimatedEmojiDrawable extends Drawable { canvas.scale(scale, scale, bounds.left + drawables[0].getIntrinsicWidth() / 2f, bounds.centerY()); } drawables[0].setBounds( - bounds.left, - bounds.centerY() - drawables[0].getIntrinsicHeight() / 2, - bounds.left + drawables[0].getIntrinsicWidth(), - bounds.centerY() + drawables[0].getIntrinsicHeight() / 2 + bounds.left, + bounds.centerY() - drawables[0].getIntrinsicHeight() / 2, + bounds.left + drawables[0].getIntrinsicWidth(), + bounds.centerY() + drawables[0].getIntrinsicHeight() / 2 ); } drawables[0].setAlpha(alpha); @@ -1185,8 +1225,10 @@ public class AnimatedEmojiDrawable extends Drawable { public void setAlpha(int i) { alpha = i; } + @Override public void setColorFilter(@Nullable ColorFilter colorFilter) {} + @Override public int getOpacity() { return PixelFormat.TRANSPARENT; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index 16326daf5..be24eda58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -23,6 +23,7 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Pair; import android.view.Gravity; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; @@ -35,6 +36,8 @@ import org.telegram.ui.ActionBar.Theme; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.stream.IntStream; public class AnimatedTextView extends View { @@ -352,6 +355,7 @@ public class AnimatedTextView extends View { CharSequence to = splitByWords ? new WordSequence(currentText) : currentText; diff(from, to, onEqualRegion, onNewPart, onOldPart); +// betterDiff(from, to, onEqualRegion, onNewPart, onOldPart); if (this.currentParts == null || this.currentParts.length != currentParts.size()) { this.currentParts = new Part[currentParts.size()]; @@ -597,6 +601,81 @@ public class AnimatedTextView extends View { return (a == null && b == null || a != null && b != null && a.charAt(aIndex) == b.charAt(bIndex)); } + private void betterDiff(final CharSequence oldText, final CharSequence newText, + RegionCallback onEqualPart, RegionCallback onNewPart, RegionCallback onOldPart) { + int m = oldText.length(); + int n = newText.length(); + + int[][] dp = new int[m+1][n+1]; + for (int i = 0; i <= m; i++) { + for (int j = 0; j <= n; j++) { + if (i == 0 || j == 0) + dp[i][j] = 0; + else if (partEquals(oldText, newText, i - 1, j - 1)) + dp[i][j] = dp[i - 1][j - 1] + 1; + else + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + + List parts = new ArrayList<>(); + int i = m, j = n; + while (i > 0 && j > 0) { + if (partEquals(oldText, newText, i - 1, j - 1)) { + int start = i-1; + while (i > 1 && j > 1 && partEquals(oldText, newText, i - 2, j - 2)) { + i--; + j--; + } + final int end = i - 1; + parts.add(() -> onEqualPart.run(oldText.subSequence(end, start + 1), end, start + 1)); + i--; + j--; + } else if (dp[i - 1][j] > dp[i][j - 1]) { + int start = i-1; + while (i > 1 && dp[i - 2][j] > dp[i - 1][j - 1]) { + i--; + } + final int end = i - 1; + parts.add(() -> onOldPart.run(oldText.subSequence(end, start + 1), end, start + 1)); + i--; + } else { + int start = j - 1; + while (j > 1 && dp[i][j - 2] > dp[i - 1][j - 1]) { + j--; + } + final int end = j - 1; + parts.add(() -> onNewPart.run(newText.subSequence(end, start + 1), end, start + 1)); + j--; + } + } + + while (i > 0) { + final int start = i - 1; + while (i > 1 && dp[i - 2][j] >= dp[i - 1][j]) { + i--; + } + final int end = i - 1; + parts.add(() -> onOldPart.run(oldText.subSequence(end, start + 1), end, start + 1)); + i--; + } + while (j > 0) { + final int start = j - 1; + while (j > 1 && dp[i][j - 2] >= dp[i][j - 1]) { + j--; + } + final int end = j - 1; + parts.add(() -> onNewPart.run(newText.subSequence(end, start + 1), end, start + 1)); + j--; + } + + Collections.reverse(parts); + for (Runnable part : parts) { + part.run(); + } + } + + private void diff(final CharSequence oldText, final CharSequence newText, RegionCallback onEqualPart, RegionCallback onNewPart, RegionCallback onOldPart) { if (updateAll) { onOldPart.run(oldText, 0, oldText.length()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index c2f3363d6..b3e2653bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -41,7 +41,7 @@ public class BackupImageView extends View { public BackupImageView(Context context) { super(context); - imageReceiver = new ImageReceiver(this); + imageReceiver = createImageReciever(); imageReceiver.setAllowLoadingOnAttachedOnly(true); imageReceiver.setDelegate((imageReceiver1, set, thumb, memCache) -> { if (set && !thumb) { @@ -50,6 +50,10 @@ public class BackupImageView extends View { }); } + protected ImageReceiver createImageReciever() { + return new ImageReceiver(this); + } + public void setBlurAllowed(boolean blurAllowed) { if (attached) { throw new IllegalStateException("You should call setBlurAllowed(...) only when detached!"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java index 56fb4e960..2b7d4330a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java @@ -947,6 +947,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private void checkDirectory(File rootDir) { File[] files = rootDir.listFiles(); + File storiesDir = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES); if (files != null) { for (int a = 0; a < files.length; a++) { File file = files[a]; @@ -954,6 +955,9 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa checkDirectory(file); continue; } + if (file.equals(storiesDir)) { + continue; + } ListItem item = new ListItem(); item.title = file.getName(); item.file = file; @@ -1165,11 +1169,17 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } currentDir = dir; listAdapter.items.clear(); + + File storiesDir = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES); for (int a = 0; a < files.length; a++) { File file = files[a]; if (file.getName().indexOf('.') == 0) { continue; } + + if (file.equals(storiesDir)) { + continue; + } ListItem item = new ListItem(); item.title = file.getName(); item.file = file; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java index 839af67bb..b74e5a08b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java @@ -164,10 +164,10 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { updateBottomViewPosition(); } - public void setPopupAlpha(float aplha) { - popupWindowLayout.setAlpha(aplha); + public void setPopupAlpha(float alpha) { + popupWindowLayout.setAlpha(alpha); if (bottomView != null) { - bottomView.setAlpha(aplha); + bottomView.setAlpha(alpha); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java index 8f2b07029..34e95b01b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java @@ -94,7 +94,7 @@ public class ColoredImageSpan extends ReplacementSpan { canvas.save(); int transY = bottom - (drawable != null ? drawable.getBounds().bottom : bottom); if (verticalAlignment == ALIGN_BASELINE) { - transY -= paint.getFontMetricsInt().descent; +// transY -= paint.getFontMetricsInt().descent; } else if (verticalAlignment == ALIGN_CENTER) { transY = top + (bottom - top) / 2 - (drawable != null ? drawable.getBounds().height() / 2 : 0); } else if (verticalAlignment == ALIGN_DEFAULT) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java index 6392677a9..c8ec60367 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java @@ -451,6 +451,9 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen } public void updateMatrix(boolean force) { + if (state == null) { + return; + } overlayMatrix.reset(); if (state.getBaseRotation() == 90 || state.getBaseRotation() == 270) { overlayMatrix.postTranslate(-state.getHeight() / 2, -state.getWidth() / 2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java index 6417073d3..d7c7daf62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java @@ -9,6 +9,8 @@ import android.text.TextPaint; import android.text.style.CharacterStyle; import android.view.View; +import org.telegram.ui.Components.Reactions.HwEmojis; + import java.util.ArrayList; public class EllipsizeSpanAnimator { @@ -81,7 +83,9 @@ public class EllipsizeSpanAnimator { a.addUpdateListener(valueAnimator -> { target.setAlpha((int) valueAnimator.getAnimatedValue()); for (int i = 0; i < ellipsizedViews.size(); i++) { - ellipsizedViews.get(i).invalidate(); + if (!HwEmojis.isHwEnabled()) { + ellipsizedViews.get(i).invalidate(); + } } }); a.setDuration(duration); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java index 827e48d6b..7ca022730 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java @@ -37,6 +37,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.Premium.PremiumLockIconView; +import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.SelectAnimatedEmojiDialog; import java.util.ArrayList; @@ -127,7 +128,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { child.setScaleX(0); child.setScaleY(0); child.setAlpha(0); - child.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + child.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); } if (id != null) { if (lastX.get(id) != null && lastX.get(id) != x) { @@ -313,6 +314,17 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { } } + public void showRecentTabStub(boolean show) { + if (recentTab == null) { + return; + } + if (show) { + recentTab.setBackground(new StabDrawable(selectorColor())); + } else { + recentTab.setBackground(null); + } + } + public void showSelected(boolean show) { this.showSelected = show; this.contentView.invalidate(); @@ -372,6 +384,37 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { return null; } + private static class StabDrawable extends Drawable { + private final Paint paint = new Paint(); + private final RectF rectF = new RectF(); + + public StabDrawable(int color){ + paint.setAlpha(45); + paint.setColor(color); + } + + @Override + public void draw(@NonNull Canvas canvas) { + rectF.set(0, 0, AndroidUtilities.dp(30), AndroidUtilities.dp(30)); + canvas.drawRoundRect(rectF, AndroidUtilities.dpf2(8), AndroidUtilities.dpf2(8), paint); + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + } + private static class DelayedAnimatedEmojiDrawable extends Drawable { int account; @@ -678,7 +721,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { if (settingsTab != null) { settingsTab.bringToFront(); if (settingsTab.getAlpha() < 1) { - settingsTab.animate().alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + settingsTab.animate().alpha(1f).setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } } // if (doAppearAnimation) { @@ -935,10 +978,21 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { imageView = new ImageView(context) { @Override public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } super.invalidate(); updateLockImageReceiver(); } + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } + @Override protected void onDraw(Canvas canvas) { @@ -966,7 +1020,23 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { } addView(imageView); - lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED, resourcesProvider); + lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED, resourcesProvider) { + @Override + public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } + }; lockView.setAlpha(0f); lockView.setScaleX(0); lockView.setScaleY(0); @@ -976,6 +1046,22 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { setColor(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider)); } + @Override + public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); @@ -1116,7 +1202,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { } }); lockAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); - lockAnimator.setDuration(200); + lockAnimator.setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200); lockAnimator.start(); } @@ -1175,7 +1261,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { if (animatedEmoji != null && attached && wasVisible) { animatedEmoji.updateView(imageView); } - if (wasVisible) { + if (wasVisible && animatedEmoji != null) { animatedEmoji.load(); } initLock(); @@ -1250,7 +1336,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { } } }); - selectAnimator.setDuration(350); + selectAnimator.setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 350); selectAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); selectAnimator.start(); } else { 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 6a7df5ef1..789826a8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -155,6 +155,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private final static int TAB_GIFS = 1; private final static int TAB_STICKERS = 2; + public int emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD; + private ArrayList allTabs = new ArrayList<>(); private ArrayList currentTabs = new ArrayList<>(); private boolean ignorePagerScroll; @@ -2838,7 +2840,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void updateEmojiDrawables() { - animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, this, getAnimatedEmojiSpans(), animatedEmojiDrawables); + animatedEmojiDrawables = AnimatedEmojiSpan.update(emojiCacheType, this, getAnimatedEmojiSpans(), animatedEmojiDrawables); } @Override 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 06f0f873e..97782f1fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -79,6 +79,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -103,6 +104,7 @@ import org.telegram.ui.Components.voip.CellFlickerDrawable; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -123,6 +125,8 @@ import javax.microedition.khronos.egl.EGLSurface; @TargetApi(18) public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + public boolean WRITE_TO_FILE_IN_BACKGROUND = true; + private int currentAccount = UserConfig.selectedAccount; private InstantViewCameraContainer cameraContainer; private Delegate delegate; @@ -1730,6 +1734,8 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private static final int IFRAME_INTERVAL = 1; private File videoFile; + private File fileToWrite; + private boolean writingToDifferentFile; private int videoWidth; private int videoHeight; private int videoBitrate; @@ -2302,6 +2308,18 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } catch (InterruptedException e) { e.printStackTrace(); } + if (writingToDifferentFile) { + if (!fileToWrite.renameTo(videoFile)) { + FileLog.e("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"); + } + } + } } if (generateKeyframeThumbsQueue != null) { generateKeyframeThumbsQueue.cleanupQueue(); @@ -2394,7 +2412,16 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter }); } else { FileLoader.getInstance(currentAccount).cancelFileUpload(videoFile.getAbsolutePath(), false); - videoFile.delete(); + try { + fileToWrite.delete(); + } catch (Throwable ignore) { + + } + try { + videoFile.delete(); + } catch (Throwable ignore) { + + } } EGL14.eglDestroySurface(eglDisplay, eglSurface); eglSurface = EGL14.EGL_NO_SURFACE; @@ -2491,8 +2518,23 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter surface = videoEncoder.createInputSurface(); videoEncoder.start(); + boolean isSdCard = ImageLoader.isSdCardPath(videoFile); + fileToWrite = videoFile; + if (isSdCard) { + try { + fileToWrite = new File(ApplicationLoader.getFilesDirFixed(), "camera_tmp.mp4"); + if (fileToWrite.exists()) { + fileToWrite.delete(); + } + writingToDifferentFile = true; + } catch (Throwable e) { + FileLog.e(e); + fileToWrite = videoFile; + writingToDifferentFile = false; + } + } Mp4Movie movie = new Mp4Movie(); - movie.setCacheFile(videoFile); + movie.setCacheFile(fileToWrite); movie.setRotation(0); movie.setSize(videoWidth, videoHeight); mediaMuxer = new MP4Builder().createMovie(movie, isSecretChat, false); @@ -2684,31 +2726,30 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } firstEncode = false; } - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.size = videoBufferInfo.size; - bufferInfo.offset = videoBufferInfo.offset; - bufferInfo.flags = videoBufferInfo.flags; - bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs; - needReleaseBuffers = false; - fileWriteQueue.postRunnable(() -> { - long availableSize = 0; - try { - availableSize = mediaMuxer.writeSampleData(videoTrackIndex, encodedData, bufferInfo, true); - } catch (Exception e) { - e.printStackTrace(); - } - MediaCodec videoEncoder = VideoRecorder.this.videoEncoder; - if (videoEncoder != null) { + if (WRITE_TO_FILE_IN_BACKGROUND) { + MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); + bufferInfo.size = videoBufferInfo.size; + bufferInfo.offset = videoBufferInfo.offset; + bufferInfo.flags = videoBufferInfo.flags; + bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs; + ByteBuffer byteBuffer = encodedData.duplicate(); + fileWriteQueue.postRunnable(() -> { + long availableSize = 0; try { - videoEncoder.releaseOutputBuffer(encoderStatus, false); - } catch (Throwable e) { - //ignore IllegalStateException if codec released + availableSize = mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo, true); + } catch (Exception e) { + e.printStackTrace(); } - } - if (availableSize != 0) { + if (availableSize != 0 && !writingToDifferentFile) { + didWriteData(videoFile, availableSize, false); + } + }); + } else { + long availableSize = mediaMuxer.writeSampleData(videoTrackIndex, encodedData, videoBufferInfo, true); + if (availableSize != 0 && !writingToDifferentFile) { didWriteData(videoFile, availableSize, false); } - }); + } } else if (videoTrackIndex == -5) { byte[] csd = new byte[videoBufferInfo.size]; encodedData.limit(videoBufferInfo.offset + videoBufferInfo.size); @@ -2780,31 +2821,33 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter audioBufferInfo.size = 0; } if (audioBufferInfo.size != 0) { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.size = audioBufferInfo.size; - bufferInfo.offset = audioBufferInfo.offset; - bufferInfo.flags = audioBufferInfo.flags; - bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs; - fileWriteQueue.postRunnable(() -> { - long availableSize = 0; - try { - availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, bufferInfo, false); - } catch (Exception e) { - e.printStackTrace(); - } - if (availableSize != 0) { + if (WRITE_TO_FILE_IN_BACKGROUND) { + MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); + bufferInfo.size = audioBufferInfo.size; + bufferInfo.offset = audioBufferInfo.offset; + bufferInfo.flags = audioBufferInfo.flags; + bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs; + ByteBuffer byteBuffer = encodedData.duplicate(); + fileWriteQueue.postRunnable(() -> { + long availableSize = 0; + try { + availableSize = mediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, bufferInfo, false); + } catch (Exception e) { + e.printStackTrace(); + } + if (availableSize != 0 && !writingToDifferentFile) { + didWriteData(videoFile, availableSize, false); + } + }); + audioEncoder.releaseOutputBuffer(encoderStatus, false); + } else { + long availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, audioBufferInfo, false); + if (availableSize != 0 && !writingToDifferentFile) { didWriteData(videoFile, availableSize, false); } - MediaCodec audioEncoder = VideoRecorder.this.audioEncoder; - if (audioEncoder != null) { - try { - audioEncoder.releaseOutputBuffer(encoderStatus, false); - } catch (Throwable e) { - //ignore IllegalStateException if codec released - } - } - }); - } else { + audioEncoder.releaseOutputBuffer(encoderStatus, false); + } + } else if (audioEncoder != null) { audioEncoder.releaseOutputBuffer(encoderStatus, false); } if ((audioBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java index faba2383c..b5e22efca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java @@ -28,6 +28,7 @@ import androidx.core.graphics.ColorUtils; import com.google.android.exoplayer2.util.Consumer; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; @@ -153,7 +154,7 @@ public class ItemOptions { } ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider); - subItem.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18 + 8), 0); + subItem.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18 + (LocaleController.isRTL ? 0 : 8)), 0); subItem.setTextAndIcon(text, iconResId); subItem.setColors(Theme.getColor(textColorKey, resourcesProvider), Theme.getColor(iconColorKey, resourcesProvider)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java index 054e150de..428f59f09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -129,7 +129,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha public boolean onFragmentCreate() { type = getArguments().getInt("type", TYPE_MEDIA); dialogId = getArguments().getLong("dialog_id"); - initialTab = getArguments().getInt("start_from", SharedMediaLayout.TAB_STORIES); + initialTab = getArguments().getInt("start_from", type == TYPE_MEDIA ? SharedMediaLayout.TAB_PHOTOVIDEO : SharedMediaLayout.TAB_STORIES); getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); getNotificationCenter().addObserver(this, NotificationCenter.storiesEnabledUpdate); @@ -612,6 +612,11 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha return type == TYPE_STORIES; } + @Override + protected boolean includeStories() { + return type == TYPE_STORIES; + } + @Override protected int getInitialTab() { return initialTab; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/PersistColorPalette.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/PersistColorPalette.java index bd9d4da2d..2dde2322e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/PersistColorPalette.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/PersistColorPalette.java @@ -141,7 +141,12 @@ public class PersistColorPalette { public int getColor(int index) { checkIndex(index); - + if (index < 0 || index >= colors.size()) { + if (index >= 0 && index < DEFAULT_COLORS.size()) { + return DEFAULT_COLORS.get(index); + } + return DEFAULT_COLORS.get(0); + } return colors.get(index); } @@ -155,12 +160,18 @@ public class PersistColorPalette { pendingChange.clear(); pendingChange.add(color); pendingChange.addAll(from); - pendingChange.remove(pendingChange.size() - 1); + if (pendingChange.size() < DEFAULT_COLORS.size()) { + for (int j = pendingChange.size(); j < DEFAULT_COLORS.size(); ++j) { + pendingChange.add(DEFAULT_COLORS.get(j)); + } + } else if (pendingChange.size() > DEFAULT_COLORS.size()) { + pendingChange = pendingChange.subList(0, DEFAULT_COLORS.size()); + } } } public void selectColorIndex(int index) { - int color = colors.get(index); + int color = index < 0 || index >= colors.size() ? DEFAULT_COLORS.get(index) : colors.get(index); List from = new ArrayList<>(pendingChange.isEmpty() ? colors : pendingChange); pendingChange.clear(); pendingChange.add(color); @@ -171,6 +182,13 @@ public class PersistColorPalette { pendingChange.add(from.get(i)); } } + if (pendingChange.size() < DEFAULT_COLORS.size()) { + for (int j = pendingChange.size(); j < DEFAULT_COLORS.size(); ++j) { + pendingChange.add(DEFAULT_COLORS.get(j)); + } + } else if (pendingChange.size() > DEFAULT_COLORS.size()) { + pendingChange = pendingChange.subList(0, DEFAULT_COLORS.size()); + } } private void loadColors() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java index e2a540d6c..384255308 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java @@ -228,8 +228,11 @@ public class EditTextOutline extends EditTextBoldCursor { } if (traceback) { for (int j = i; j >= 1; --j) { - above = lines[i - 1]; + above = lines[j - 1]; line = lines[j]; + if (above.width() < dp(1) || line.width() < dp(1)) { + continue; + } if (Math.abs(above.left - line.left) < mr) { line.left = above.left = Math.min(line.left, above.left); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java index aa26fbb14..163a8d27f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java @@ -27,6 +27,7 @@ import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.Paint.Views.EditTextOutline; import org.telegram.ui.Components.Paint.Views.PaintTextOptionsView; @@ -252,22 +253,22 @@ public class PaintingOverlay extends FrameLayout { if (Build.VERSION.SDK_INT >= 23) { editText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE); } - if ((entity.subType & 1) != 0) { - editText.setTextColor(0xffffffff); - editText.setStrokeColor(entity.color); - editText.setFrameColor(0); - editText.setShadowLayer(0, 0, 0, 0); - } else if ((entity.subType & 4) != 0) { - editText.setTextColor(0xff000000); - editText.setStrokeColor(0); + editText.setShadowLayer(0, 0, 0, 0); + int textColor = entity.color; + if (entity.subType == 0) { editText.setFrameColor(entity.color); - editText.setShadowLayer(0, 0, 0, 0); + textColor = AndroidUtilities.computePerceivedBrightness(entity.color) >= .721f ? Color.BLACK : Color.WHITE; + } else if (entity.subType == 1) { + editText.setFrameColor(AndroidUtilities.computePerceivedBrightness(entity.color) >= .25f ? 0x99000000 : 0x99ffffff); + } else if (entity.subType == 2) { + editText.setFrameColor(AndroidUtilities.computePerceivedBrightness(entity.color) >= .25f ? Color.BLACK : Color.WHITE); } else { - editText.setTextColor(entity.color); - editText.setStrokeColor(0); editText.setFrameColor(0); - editText.setShadowLayer(5, 0, 1, 0x66000000); } + editText.setTextColor(textColor); + editText.setCursorColor(textColor); + editText.setHandlesColor(textColor); + editText.setHighlightColor(Theme.multAlpha(textColor, .4f)); entity.view = child = editText; } if (child != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index 0a261ff5b..c9272da4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -623,6 +623,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica return -10177041; } else if (key == Theme.key_dialogFloatingIcon) { return 0xffffffff; + } else if (key == Theme.key_chat_emojiPanelStickerSetName) { + return 0x73ffffff; } return 0; } @@ -637,6 +639,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica return; } emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider); + emojiView.emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { @Override public boolean onBackspace() { @@ -712,6 +715,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica } if (!isRecent) { span.fromEmojiKeyboard = true; + span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; } spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); messageEditText.setText(messageEditText.getText().insert(i, spannable)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java index 198901b40..9358c9a92 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java @@ -70,6 +70,7 @@ public class PremiumButtonView extends FrameLayout { LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); buttonTextView = new AnimatedTextView(context); + buttonTextView.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); buttonTextView.setGravity(Gravity.CENTER); buttonTextView.setTextColor(Color.WHITE); buttonTextView.setTextSize(AndroidUtilities.dp(14)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java index 114b953d9..e52e253b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java @@ -7,6 +7,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; @@ -15,10 +16,12 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.os.Build; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.View; +import android.view.ViewOutlineProvider; import android.view.WindowManager; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; @@ -43,9 +46,11 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EmojiTabsStrip; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.ReactionsContainerLayout; +import org.telegram.ui.Components.StableAnimator; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.SelectAnimatedEmojiDialog; @@ -70,7 +75,7 @@ public class CustomEmojiReactionsWindow { SelectAnimatedEmojiDialog selectAnimatedEmojiDialog; ReactionsContainerLayout reactionsContainerLayout; - Path pathToClip = new Path(); + private final Path pathToClipApi20 = new Path(); private boolean invalidatePath; List reactions; @@ -199,6 +204,24 @@ public class CustomEmojiReactionsWindow { containerView.invalidate(); } }; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + selectAnimatedEmojiDialog.setOutlineProvider(new ViewOutlineProvider() { + final Rect rect = new Rect(); + final RectF rectTmp = new RectF(); + final RectF rectF = new RectF(); + + @Override + public void getOutline(View view, Outline outline) { + float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress); + rectTmp.set(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + AndroidUtilities.lerp(fromRect, rectTmp, enterTransitionProgress, rectF); + rectF.round(rect); + outline.setRoundRect(rect, radius); + } + }); + selectAnimatedEmojiDialog.setClipToOutline(true); + } + selectAnimatedEmojiDialog.setOnLongPressedListener(new SelectAnimatedEmojiDialog.onLongPressedListener() { @Override public void onLongPressed(SelectAnimatedEmojiDialog.ImageViewEmoji view) { @@ -234,6 +257,7 @@ public class CustomEmojiReactionsWindow { windowManager.addView(windowView, lp); this.reactionsContainerLayout = reactionsContainerLayout; + reactionsContainerLayout.setOnSwitchedToLoopView(() -> containerView.invalidate()); //fixed emoji freeze reactionsContainerLayout.prepareAnimation(true); AndroidUtilities.runOnUIThread(() -> { isShowing = true; @@ -333,50 +357,57 @@ public class CustomEmojiReactionsWindow { cascadeAnimation = false; } if (cascadeAnimation) { - updateCascadeEnter(0); + updateCascadeEnter(0, true); } + updateContainersAlpha(); selectAnimatedEmojiDialog.setEnterAnimationInProgress(true); + selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(enter && cascadeAnimation); account = UserConfig.selectedAccount; notificationsLocker.lock(); - valueAnimator = ValueAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); + valueAnimator = StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); valueAnimator.addUpdateListener(animation -> { valueAnimator = null; enterTransitionProgress = (float) animation.getAnimatedValue(); - reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress,1f, 0)); + updateContainersAlpha(); + updateContentPosition(); + reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0)); invalidatePath = true; containerView.invalidate(); - + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + selectAnimatedEmojiDialog.invalidateOutline(); + } if (cascadeAnimation) { - updateCascadeEnter(enterTransitionProgress); + updateCascadeEnter(enterTransitionProgress, enter); } }); if (!enter) { - syncReactionFrames(enter); + syncReactionFrames(); } valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { - checkAnimationEnd(); + updateContainersAlpha(); + updateContentPosition(); + checkAnimationEnd(enter); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + selectAnimatedEmojiDialog.invalidateOutline(); + } enterTransitionProgress = enter ? 1f : 0f; if (enter) { enterTransitionFinished = true; - selectAnimatedEmojiDialog.resetBackgroundBitmaps(); - reactionsContainerLayout.onCustomEmojiWindowOpened(); containerView.invalidate(); } reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0f)); - if (enter) { - syncReactionFrames(enter); - } if (!enter) { reactionsContainerLayout.setSkipDraw(false); - } - if (!enter) { removeView(); + Runtime.getRuntime().gc(); //to prevent garbage collection when reopening + reactionsContainerLayout.setCustomEmojiReactionsBackground(true); } } }); - valueAnimator.setStartDelay(30); + if (cascadeAnimation) { valueAnimator.setDuration(450); valueAnimator.setInterpolator(new OvershootInterpolator(0.5f)); @@ -384,15 +415,68 @@ public class CustomEmojiReactionsWindow { valueAnimator.setDuration(350); valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); } - valueAnimator.start(); containerView.invalidate(); + switchLayerType(true); + if (!enter) { + reactionsContainerLayout.isHiddenNextReaction = true; + reactionsContainerLayout.invalidate(); + valueAnimator.setStartDelay(30); + valueAnimator.start(); + } else { + reactionsContainerLayout.setCustomEmojiReactionsBackground(false); + final ValueAnimator finalAnimator = valueAnimator; + HwEmojis.prepare(finalAnimator::start, cascadeAnimation); + } + HwEmojis.enableHw(); + } + + private void updateContainersAlpha() { + if (!cascadeAnimation) { + selectAnimatedEmojiDialog.searchBox.setAlpha(enterTransitionProgress); + selectAnimatedEmojiDialog.emojiGridView.setAlpha(enterTransitionProgress); + selectAnimatedEmojiDialog.emojiSearchGridView.setAlpha(enterTransitionProgress); + selectAnimatedEmojiDialog.emojiTabs.setAlpha(enterTransitionProgress); + selectAnimatedEmojiDialog.emojiTabsShadow.setAlpha(enterTransitionProgress); + } + } + + private void updateContentPosition() { + selectAnimatedEmojiDialog.contentView.setTranslationX(cascadeAnimation ? 0 : containerView.enterTransitionOffsetX); + selectAnimatedEmojiDialog.contentView.setTranslationY(containerView.enterTransitionOffsetY); + selectAnimatedEmojiDialog.contentView.setPivotX(containerView.enterTransitionScalePx); + selectAnimatedEmojiDialog.contentView.setPivotY(containerView.enterTransitionScalePy); + selectAnimatedEmojiDialog.contentView.setScaleX(containerView.enterTransitionScale); + selectAnimatedEmojiDialog.contentView.setScaleY(containerView.enterTransitionScale); + } + + private void switchLayerType(boolean hardware) { + int layerType = hardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; + selectAnimatedEmojiDialog.emojiGridView.setLayerType(layerType, null); + selectAnimatedEmojiDialog.searchBox.setLayerType(layerType, null); + if (cascadeAnimation) { + for (int i = 0; i < Math.min(selectAnimatedEmojiDialog.emojiTabs.contentView.getChildCount(), 16); i++) { + View child = selectAnimatedEmojiDialog.emojiTabs.contentView.getChildAt(i); + child.setLayerType(layerType, null); + } + } else { + selectAnimatedEmojiDialog.emojiTabsShadow.setLayerType(layerType, null); + selectAnimatedEmojiDialog.emojiTabs.setLayerType(layerType, null); + } } HashSet animatingEnterChild = new HashSet<>(); ArrayList animators = new ArrayList<>(); - private void updateCascadeEnter(float progress) { - int fullHeight = selectAnimatedEmojiDialog.contentView.getHeight(); + private void setScaleForChild(View child, float value) { + if (child instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) { + ((SelectAnimatedEmojiDialog.ImageViewEmoji) child).setAnimatedScale(value); + } else if (child instanceof EmojiTabsStrip.EmojiTabButton) { + child.setScaleX(value); + child.setScaleY(value); + } + } + + private void updateCascadeEnter(float progress, boolean enter) { int parentTop = (int) (selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.contentView.getY() + selectAnimatedEmojiDialog.emojiGridView.getY()); ArrayList animatedViews = null; boolean updated = false; @@ -409,8 +493,7 @@ public class CustomEmojiReactionsWindow { animatedViews.add(child); animatingEnterChild.add(child); } else { - child.setScaleX(0f); - child.setScaleY(0f); + setScaleForChild(child, 0f); updated = true; } } @@ -428,15 +511,12 @@ public class CustomEmojiReactionsWindow { animatedViews.add(child); animatingEnterChild.add(child); } else { - child.setScaleX(0f); - child.setScaleY(0f); + setScaleForChild(child, 0f); updated = true; } } if (updated) { - selectAnimatedEmojiDialog.emojiGridView.invalidate(); - selectAnimatedEmojiDialog.contentView.invalidate(); - selectAnimatedEmojiDialog.emojiTabs.contentView.invalidate(); + selectAnimatedEmojiDialog.emojiGridViewContainer.invalidate(); } if (animatedViews != null) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); @@ -444,12 +524,10 @@ public class CustomEmojiReactionsWindow { valueAnimator.addUpdateListener(animation -> { float s = (float) animation.getAnimatedValue(); for (int i = 0; i < finalAnimatedViews.size(); i++) { - finalAnimatedViews.get(i).setScaleX(s); - finalAnimatedViews.get(i).setScaleY(s); + View v = finalAnimatedViews.get(i); + setScaleForChild(v, s); } - selectAnimatedEmojiDialog.emojiGridView.invalidate(); - selectAnimatedEmojiDialog.contentView.invalidate(); - selectAnimatedEmojiDialog.emojiTabs.contentView.invalidate(); + selectAnimatedEmojiDialog.emojiGridViewContainer.invalidate(); }); animators.add(valueAnimator); valueAnimator.addListener(new AnimatorListenerAdapter() { @@ -457,7 +535,7 @@ public class CustomEmojiReactionsWindow { public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); animators.remove(valueAnimator); - checkAnimationEnd(); + checkAnimationEnd(enter); } }); valueAnimator.setDuration(350); @@ -466,16 +544,32 @@ public class CustomEmojiReactionsWindow { } } - private void checkAnimationEnd() { + private void checkAnimationEnd(boolean enter) { if (animators.isEmpty()) { + switchLayerType(false); + HwEmojis.disableHw(); notificationsLocker.unlock(); selectAnimatedEmojiDialog.setEnterAnimationInProgress(false); + if (enter) { + selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(false); + selectAnimatedEmojiDialog.emojiGridView.invalidate(); + selectAnimatedEmojiDialog.emojiGridView.invalidateViews(); + selectAnimatedEmojiDialog.searchBox.checkInitialization(); + if (reactionsContainerLayout.getPullingLeftProgress() > 0) { + reactionsContainerLayout.isHiddenNextReaction = false; + reactionsContainerLayout.onCustomEmojiWindowOpened(); + } else { + reactionsContainerLayout.isHiddenNextReaction = true; + reactionsContainerLayout.onCustomEmojiWindowOpened(); + } + selectAnimatedEmojiDialog.resetBackgroundBitmaps(); + syncReactionFrames(); + containerView.invalidate(); + } } } - private void syncReactionFrames(boolean enter) { - HashMap transitionReactions = new HashMap<>(); - + private void syncReactionFrames() { for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) { if (selectAnimatedEmojiDialog.emojiGridView.getChildAt(i) instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) { SelectAnimatedEmojiDialog.ImageViewEmoji imageViewEmoji = (SelectAnimatedEmojiDialog.ImageViewEmoji) selectAnimatedEmojiDialog.emojiGridView.getChildAt(i); @@ -562,7 +656,7 @@ public class CustomEmojiReactionsWindow { windowView.animate().alpha(0).setDuration(150).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - checkAnimationEnd(); + checkAnimationEnd(false); enterTransitionProgress = 0f; reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0f)); reactionsContainerLayout.setSkipDraw(false); @@ -620,6 +714,12 @@ public class CustomEmojiReactionsWindow { HashMap transitionReactions = new HashMap<>(); + float enterTransitionOffsetX = 0; + float enterTransitionOffsetY = 0; + float enterTransitionScale = 1f; + float enterTransitionScalePx = 0; + float enterTransitionScalePy = 0; + @Override protected void dispatchDraw(Canvas canvas) { if (!isShowing) { @@ -649,11 +749,11 @@ public class CustomEmojiReactionsWindow { reactionsContainerLayout.drawBubbles(canvas); canvas.restore(); } - float enterTransitionOffsetX = 0; - float enterTransitionOffsetY = 0; - float enterTransitionScale = 1f; - float enterTransitionScalePx = 0; - float enterTransitionScalePy = 0; + enterTransitionOffsetX = 0; + enterTransitionOffsetY = 0; + enterTransitionScale = 1f; + enterTransitionScalePx = 0; + enterTransitionScalePy = 0; if (reactionsContainerLayout != null) { for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) { @@ -669,7 +769,8 @@ public class CustomEmojiReactionsWindow { canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.expandSize() * (1f - enterTransitionProgress)); - float alpha = Math.max(selectAnimatedEmojiDialog.emojiGridView.getAlpha(), 1f - enterTransitionProgress); + float a = selectAnimatedEmojiDialog.emojiSearchGridView.getVisibility() == View.VISIBLE ? selectAnimatedEmojiDialog.emojiSearchGridView.getAlpha() : 0; + float alpha = Math.max(1f - a, 1f - enterTransitionProgress); if (alpha != 1f) { canvas.saveLayerAlpha(0, 0, drawingRect.width(), drawingRect.height(), (int) (255 * alpha), Canvas.ALL_SAVE_FLAG); } @@ -678,9 +779,6 @@ public class CustomEmojiReactionsWindow { canvas.clipRect(left, top + AndroidUtilities.dp(36) * enterTransitionProgress, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth()); for (int i = -1; i < reactionsContainerLayout.recyclerListView.getChildCount(); i++) { View child; - if (enterTransitionProgress == 1 && i == -1) { - continue; - } if (i == -1) { child = reactionsContainerLayout.nextRecentReaction; } else { @@ -802,6 +900,9 @@ public class CustomEmojiReactionsWindow { imageReceiver.setAlpha(oldAlpha); } } + if (holderView.loopImageView.getVisibility() != View.VISIBLE) { + invalidate(); + } } else { canvas.translate(child.getX() + drawingRect.width() - reactionsContainerLayout.rect.width(), child.getY() + fromRect.top - drawingRect.top); canvas.saveLayerAlpha(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight(), (int) (255 * (1f - progressClpamped)), Canvas.ALL_SAVE_FLAG); @@ -814,20 +915,20 @@ public class CustomEmojiReactionsWindow { canvas.restoreToCount(restoreCount); } - if (invalidatePath) { - invalidatePath = false; - pathToClip.rewind(); - pathToClip.addRoundRect(drawingRect, radius, radius, Path.Direction.CW); + boolean beforeLollipop = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; + if (beforeLollipop) { + if (invalidatePath) { + invalidatePath = false; + pathToClipApi20.rewind(); + pathToClipApi20.addRoundRect(drawingRect, radius, radius, Path.Direction.CW); + } + canvas.save(); + canvas.clipPath(pathToClipApi20); + super.dispatchDraw(canvas); + canvas.restore(); + } else { + super.dispatchDraw(canvas); } - canvas.save(); - canvas.clipPath(pathToClip); - canvas.translate(cascadeAnimation ? 0 : enterTransitionOffsetX, enterTransitionOffsetY); - canvas.scale(enterTransitionScale, enterTransitionScale, enterTransitionScalePx, enterTransitionScalePy); - if (!cascadeAnimation) { - selectAnimatedEmojiDialog.setAlpha(enterTransitionProgress); - } - super.dispatchDraw(canvas); - canvas.restore(); if (frameDrawCount < 5) { if (frameDrawCount == 3) { @@ -840,6 +941,7 @@ public class CustomEmojiReactionsWindow { if (valueAnimator != null) { invalidate(); } + HwEmojis.exec(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/HwEmojis.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/HwEmojis.java new file mode 100644 index 000000000..a5d02fb8a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/HwEmojis.java @@ -0,0 +1,106 @@ +package org.telegram.ui.Components.Reactions; + +import static org.telegram.messenger.SharedConfig.PERFORMANCE_CLASS_HIGH; +import static org.telegram.messenger.SharedConfig.getDevicePerformanceClass; + +import android.view.View; + +import org.telegram.messenger.ImageLoader; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class HwEmojis { + private static final Set hwViews = new HashSet<>(); + private static volatile boolean hwEnabled = false; + private static Runnable task; + private static boolean firstOpen = true; + private static boolean isPreparing = false; + private static boolean isCascade = false; + private static boolean isBeforePreparing = false; + private static Boolean isWeakDevice; + + public static void prepare(Runnable runnable, boolean cascade) { + isCascade = cascade; + isPreparing = true; + isBeforePreparing = false; + if (firstOpen) { + firstOpen = false; + } + task = runnable; + } + + public static void beforePreparing() { + ImageLoader.getInstance().getCacheOutQueue().pause(); + isBeforePreparing = true; + } + + public static boolean isCascade() { + return isCascade; + } + + public static boolean isPreparing() { + return isPreparing; + } + + public static boolean isFirstOpen() { + return firstOpen; + } + + public static boolean isHwEnabled() { + return hwEnabled; + } + + public static boolean isHwEnabledOrPreparing() { + return hwEnabled || isPreparing || isBeforePreparing; + } + + public static void exec() { + if (task != null) { + task.run(); + task = null; + } + } + + public static boolean grab(View view) { + if (hwEnabled) { + hwViews.add(view); + } + return hwEnabled; + } + + public static boolean grabIfWeakDevice(View... views) { + if (isWeakDevice == null) { + isWeakDevice = getDevicePerformanceClass() != PERFORMANCE_CLASS_HIGH; + } + + if (!isWeakDevice) { + return false; + } + + if (hwEnabled) { + hwViews.addAll(Arrays.asList(views)); + } + return hwEnabled; + } + + public static void enableHw() { + ImageLoader.getInstance().getCacheOutQueue().pause(); + hwEnabled = true; + isPreparing = false; + isBeforePreparing = false; + } + + public static void disableHw() { + ImageLoader.getInstance().getCacheOutQueue().resume(); + hwEnabled = false; + isPreparing = false; + isBeforePreparing = false; + task = null; + for (View view : hwViews) { + view.invalidate(); + } + hwViews.clear(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java index fe1ae5741..6345b698a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -61,10 +61,12 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ReactedUserHolderView; import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumLockIconView; import org.telegram.ui.Components.Reactions.CustomEmojiReactionsWindow; +import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; @@ -170,6 +172,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio final AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(); private final int type; public boolean skipEnterAnimation; + public boolean isHiddenNextReaction = true; + private Runnable onSwitchedToLoopView; public ReactionsContainerLayout(int type, BaseFragment fragment, @NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -195,6 +199,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow), PorterDuff.Mode.MULTIPLY)); recyclerListView = new RecyclerListView(context) { + @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { if (pressedReaction != null && (child instanceof ReactionHolderView) && ((ReactionHolderView) child).currentReaction.equals(pressedReaction)) { @@ -506,6 +511,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } } + public void setOnSwitchedToLoopView(Runnable onSwitchedToLoopView) { + this.onSwitchedToLoopView = onSwitchedToLoopView; + } + public void dismissWindow() { reactionsWindow.dismiss(); } @@ -519,8 +528,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio return; } reactionsWindow = new CustomEmojiReactionsWindow(type, fragment, allReactionsList, selectedReactions, this, resourcesProvider); + invalidateLoopViews(); reactionsWindow.onDismissListener(() -> { reactionsWindow = null; + invalidateLoopViews(); if (delegate != null) { delegate.onEmojiWindowDismissed(); } @@ -528,6 +539,15 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio //animatePullingBack(); } + private void invalidateLoopViews() { + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + if (child instanceof ReactionHolderView) { + ((ReactionHolderView) child).loopImageView.invalidate(); + } + } + } + public boolean showCustomEmojiReaction() { return !MessagesController.getInstance(currentAccount).premiumLocked && allReactionsAvailable; } @@ -761,9 +781,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } if (pullingLeftOffsetProgress > 0) { float progress = getPullingLeftProgress(); - int left = lastReactionX + AndroidUtilities.dp(32); - float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - AndroidUtilities.dp(34)), 1f, 0f); - float pullingOffsetX = leftProgress * progress * AndroidUtilities.dp(32); + int reactionSize = nextRecentReaction.getMeasuredWidth() - AndroidUtilities.dp(2); + int left = lastReactionX + reactionSize; + float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - nextRecentReaction.getMeasuredWidth()), 1f, 0f); + float pullingOffsetX = leftProgress * progress * reactionSize; if (nextRecentReaction.getTag() == null) { nextRecentReaction.setTag(1f); @@ -773,10 +794,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio float scale = Utilities.clamp(progress, 1f, 0f); nextRecentReaction.setScaleX(scale); nextRecentReaction.setScaleY(scale); - nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX - AndroidUtilities.dp(20)); - nextRecentReaction.setVisibility(View.VISIBLE); + float additionalOffset = 0; + if (type != TYPE_STORY) { + additionalOffset = - AndroidUtilities.dp(20); + } else { + additionalOffset = - AndroidUtilities.dp(8); + } + nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX + additionalOffset); + if (nextRecentReaction.getVisibility() != View.VISIBLE) { + nextRecentReaction.setVisibility(View.VISIBLE); + } } else { - nextRecentReaction.setVisibility(View.GONE); + if (nextRecentReaction.getVisibility() != View.GONE && isHiddenNextReaction) { + nextRecentReaction.setVisibility(View.GONE); + } if (nextRecentReaction.getTag() != null) { nextRecentReaction.setTag(null); } @@ -791,20 +822,25 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio return; } - canvas.clipPath(mPath); + boolean showCustomEmojiReaction = showCustomEmojiReaction(); + if (!showCustomEmojiReaction) { + canvas.clipPath(mPath); + } canvas.translate((LocaleController.isRTL || mirrorX ? -1 : 1) * getWidth() * (1f - transitionProgress), 0); recyclerListView.setTranslationX(-transitionLeftOffset); super.dispatchDraw(canvas); - if (leftShadowPaint != null) { - float p = Utilities.clamp(leftAlpha * transitionProgress, 1f, 0f); - leftShadowPaint.setAlpha((int) (p * 0xFF)); - canvas.drawRect(rect, leftShadowPaint); - } - if (rightShadowPaint != null) { - float p = Utilities.clamp(rightAlpha * transitionProgress, 1f, 0f); - rightShadowPaint.setAlpha((int) (p * 0xFF)); - canvas.drawRect(rect, rightShadowPaint); + if (!showCustomEmojiReaction) { + if (leftShadowPaint != null) { + float p = Utilities.clamp(leftAlpha * transitionProgress, 1f, 0f); + leftShadowPaint.setAlpha((int) (p * 0xFF)); + canvas.drawRect(rect, leftShadowPaint); + } + if (rightShadowPaint != null) { + float p = Utilities.clamp(rightAlpha * transitionProgress, 1f, 0f); + rightShadowPaint.setAlpha((int) (p * 0xFF)); + canvas.drawRect(rect, rightShadowPaint); + } } canvas.restoreToCount(s); @@ -824,7 +860,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio return; } canvas.save(); - float scale = transitionProgress; canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)), getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + AndroidUtilities.dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress))); float cx = LocaleController.isRTL || mirrorX ? bigCircleOffset : getWidth() - bigCircleOffset; float cy = getHeight() - getPaddingBottom() + expandSize(); @@ -937,7 +972,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } } - private float getPullingLeftProgress() { + public float getPullingLeftProgress() { return Utilities.clamp(pullingLeftOffset / AndroidUtilities.dp(42), 2f, 0f); } @@ -1160,6 +1195,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio invalidate(); } + public void setCustomEmojiReactionsBackground(boolean isNeed) { + if (isNeed) { + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + } else { + customEmojiReactionsIconView.setBackground(null); + } + } + boolean skipDraw; public void setSkipDraw(boolean b) { @@ -1185,7 +1228,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public void onCustomEmojiWindowOpened() { - animatePullingBack(); + pullingLeftOffset = 0f; + if (customReactionsContainer != null) { + customReactionsContainer.invalidate(); + } + invalidate(); } public void clearRecentReactions() { @@ -1337,6 +1384,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio this.recyclerReaction = recyclerReaction; enterImageView = new BackupImageView(context) { + @Override + protected ImageReceiver createImageReciever() { + return new ImageReceiver(this) { + @Override + protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) { + if (drawable instanceof RLottieDrawable) { + RLottieDrawable rLottieDrawable = (RLottieDrawable) drawable; + rLottieDrawable.setCurrentFrame(0, false, true); + } + return super.setImageBitmapByKey(drawable, key, type, memCache, guid); + } + }; + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); @@ -1347,6 +1408,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio switchedToLoopView = true; loopImageView.imageReceiver.getLottieAnimation().setCurrentFrame(0, false, true); loopImageView.setVisibility(View.VISIBLE); + if (onSwitchedToLoopView != null) { + onSwitchedToLoopView.run(); + } AndroidUtilities.runOnUIThread(() -> { enterImageView.setVisibility(View.INVISIBLE); }); @@ -1356,21 +1420,97 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio @Override public void invalidate() { + if (HwEmojis.grabIfWeakDevice(this, ReactionsContainerLayout.this)) { + return; + } super.invalidate(); ReactionsContainerLayout.this.invalidate(); } @Override public void invalidate(Rect dirty) { + if (HwEmojis.grabIfWeakDevice(this, ReactionsContainerLayout.this)) { + return; + } super.invalidate(dirty); ReactionsContainerLayout.this.invalidate(); } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grabIfWeakDevice(this)) { + return; + } + super.invalidate(l, t, r, b); + } + }; + loopImageView = new BackupImageView(context) { + + @Override + protected void onDraw(Canvas canvas) { + ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver; + if (imageReceiver != null && imageReceiver.getLottieAnimation() != null) { + if (reactionsWindow != null || pressed) { + imageReceiver.getLottieAnimation().start(); + } else { + if (imageReceiver.getLottieAnimation().getCurrentFrame() <= 2) { + imageReceiver.getLottieAnimation().stop(); + } + } + } + super.onDraw(canvas); + + } + + @Override + protected ImageReceiver createImageReciever() { + return new ImageReceiver(this) { + + @Override + protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) { + boolean rez = super.setImageBitmapByKey(drawable, key, type, memCache, guid); + if (rez) { + if (drawable instanceof RLottieDrawable) { + RLottieDrawable rLottieDrawable = (RLottieDrawable) drawable; + rLottieDrawable.setCurrentFrame(0, false, true); + rLottieDrawable.stop(); + } + } + return rez; + } + }; + } + + @Override + public void invalidate() { + if (HwEmojis.grabIfWeakDevice(this)) { + return; + } + super.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grabIfWeakDevice(this)) { + return; + } + super.invalidate(l, t, r, b); + } }; - loopImageView = new BackupImageView(context); enterImageView.getImageReceiver().setAutoRepeat(0); enterImageView.getImageReceiver().setAllowStartLottieAnimation(false); pressedBackupImageView = new BackupImageView(context) { + + @Override + protected void onDraw(Canvas canvas) { + ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver; + if (imageReceiver != null && imageReceiver.getLottieAnimation() != null) { + imageReceiver.getLottieAnimation().start(); + } + super.onDraw(canvas); + } + @Override public void invalidate() { super.invalidate(); @@ -1382,6 +1522,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio addView(loopImageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER)); enterImageView.setLayerNum(Integer.MAX_VALUE); loopImageView.setLayerNum(Integer.MAX_VALUE); + loopImageView.imageReceiver.setAutoRepeat(0); + loopImageView.imageReceiver.setAllowStartAnimation(false); + loopImageView.imageReceiver.setAllowStartLottieAnimation(false); pressedBackupImageView.setLayerNum(Integer.MAX_VALUE); } @@ -1413,7 +1556,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio loopImageView.setAnimatedEmojiDrawable(loopDrawable); } setFocusable(true); - shouldSwitchToLoopView = hasEnterAnimation && showCustomEmojiReaction(); + shouldSwitchToLoopView = hasEnterAnimation && !allReactionsIsDefault; if (!hasEnterAnimation) { enterImageView.setVisibility(View.GONE); loopImageView.setVisibility(View.VISIBLE); @@ -1448,6 +1591,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio enterImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.appear_animation), ReactionsUtils.APPEAR_ANIMATION_FILTER, null, null, svgThumb, 0, "tgs", react, 0); loopImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.select_animation), ReactionsUtils.SELECT_ANIMATION_FILTER, null, null, hasEnterAnimation ? null : svgThumb, 0, "tgs", currentReaction, 0); } + if (enterImageView.getImageReceiver().getLottieAnimation() != null) { + enterImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false, true); + } pressedBackupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.select_animation), ReactionsUtils.SELECT_ANIMATION_FILTER, null, null, svgThumb, 0, "tgs", react, 0); preloadImageReceiver.setAllowStartLottieAnimation(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index 8775e5c81..dcc316cf8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -1053,7 +1053,9 @@ public class RecyclerListView extends RecyclerView { final View view = cv; final int position = currentChildPosition; if (instantClick && position != -1) { - view.playSoundEffect(SoundEffectConstants.CLICK); + try { + view.playSoundEffect(SoundEffectConstants.CLICK); + } catch (Exception ignore) {} view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); if (onItemClickListener != null) { onItemClickListener.onItemClick(view, position); @@ -1070,7 +1072,9 @@ public class RecyclerListView extends RecyclerView { if (view != null) { onChildPressed(view, 0, 0, false); if (!instantClick) { - view.playSoundEffect(SoundEffectConstants.CLICK); + try { + view.playSoundEffect(SoundEffectConstants.CLICK); + } catch (Exception ignore) {} view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); if (position != -1) { if (onItemClickListener != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index bb7c3ff20..f852764b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -1880,10 +1880,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (archivedHintLayout == null || archivedHintLayout.getWidth() != width) { archivedHintLayout = new StaticLayout(LocaleController.getString("ProfileStoriesArchiveHint", R.string.ProfileStoriesArchiveHint), archivedHintPaint, width, Layout.Alignment.ALIGN_CENTER, 1f, 0f, false); archivedHintLayoutWidth = 0; + archivedHintLayoutLeft = 0; for (int i = 0; i < archivedHintLayout.getLineCount(); ++i) { archivedHintLayoutWidth = Math.max(archivedHintLayoutWidth, archivedHintLayout.getLineWidth(i)); + archivedHintLayoutLeft = Math.min(archivedHintLayoutLeft, archivedHintLayout.getLineLeft(i)); } - archivedHintLayoutLeft = archivedHintLayout.getLineCount() > 0 ? archivedHintLayout.getLineLeft(0) : 0; } canvas.save(); @@ -2269,10 +2270,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (mediaPage.selectedType == TAB_GROUPUSERS) { if (view instanceof UserCell) { TLRPC.ChatParticipant participant; + final int i; if (!chatUsersAdapter.sortedUsers.isEmpty()) { - participant = chatUsersAdapter.chatInfo.participants.participants.get(chatUsersAdapter.sortedUsers.get(position)); + i = chatUsersAdapter.sortedUsers.get(position); } else { - participant = chatUsersAdapter.chatInfo.participants.participants.get(position); + i = position; + } + participant = chatUsersAdapter.chatInfo.participants.participants.get(i); + if (i < 0 || i >= chatUsersAdapter.chatInfo.participants.participants.size()) { + return; } onMemberClick(participant, false, view); } else if (mediaPage.listView.getAdapter() == groupUsersSearchAdapter) { @@ -2508,6 +2514,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter return false; } + protected boolean includeStories() { + return true; + } + protected int getInitialTab() { return 0; } @@ -4822,7 +4832,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (changed > 3) { idToView = null; } - if (DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView())) { + if (DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView()) && includeStories()) { if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) { scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StableAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StableAnimator.java new file mode 100644 index 000000000..03adb6dc4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StableAnimator.java @@ -0,0 +1,68 @@ +package org.telegram.ui.Components; + +import android.animation.TimeAnimator; + +import org.telegram.messenger.AndroidUtilities; + +/** + * Good for animations with a jank at the beginning. + */ +public class StableAnimator extends TimeAnimator { + private int times = 0; + private int totalTimes = 0; + private AnimatorUpdateListener updateListener; + private Object animatedValue; + private float[] floatValues; + + public static StableAnimator ofFloat(float... values) { + StableAnimator anim = new StableAnimator(); + anim.setFloatValues(values); + return anim; + } + + @Override + public void setFloatValues(float[] floatValues) { + super.setFloatValues(floatValues); + this.floatValues = floatValues; + } + + @Override + public void addUpdateListener(AnimatorUpdateListener listener) { + updateListener = listener; + } + + @Override + public Object getAnimatedValue() { + return animatedValue; + } + + @Override + public void end() { + updateListener = null; + super.end(); + } + + @Override + public void start() { + setTimeListener((animation, totalTime, deltaTime) -> { + if (times > 0 && totalTimes > 0) { + times--; + if (updateListener != null) { + if (floatValues != null && floatValues.length == 2) { + float percent = (float) times / (float) totalTimes; + float fraction = getInterpolator().getInterpolation(1f - percent); + animatedValue = floatValues[0] + ((floatValues[1] - floatValues[0]) * fraction); + updateListener.onAnimationUpdate(this); + } else { + end(); + } + } + } else { + end(); + } + }); + this.times = (int) (getDuration() / AndroidUtilities.screenRefreshTime); + this.totalTimes = this.times; + super.start(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index 5434d6cc0..7de5f6732 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -18,6 +18,8 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; @@ -133,6 +135,10 @@ public class StaticLayoutEx { }*/ try { if (maxLines == 1) { + int index = TextUtils.indexOf(source, "\n") - 1; + if (index > 0) { + source = SpannableStringBuilder.valueOf(source.subSequence(0, index)).append("…"); + } CharSequence text = TextUtils.ellipsize(source, paint, ellipsisWidth, TextUtils.TruncateAt.END); return new StaticLayout(text, 0, text.length(), paint, outerWidth, align, spacingMult, spacingAdd, includePad); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java index 784bbe108..2a957d7ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java @@ -5,6 +5,7 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Configuration; import android.graphics.Canvas; @@ -32,6 +33,7 @@ import org.telegram.messenger.CacheFetcher; import org.telegram.messenger.FileLog; import org.telegram.messenger.LiteMode; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -114,6 +116,7 @@ public class StickerCategoriesListView extends RecyclerListView { this(context, additionalCategories, categoriesType, null); } + @SuppressLint("NotifyDataSetChanged") public StickerCategoriesListView(Context context, EmojiCategory[] additionalCategories, @CategoriesType int categoriesType, Theme.ResourcesProvider resourcesProvider) { super(context, resourcesProvider); @@ -136,19 +139,22 @@ public class StickerCategoriesListView extends RecyclerListView { long start = System.currentTimeMillis(); fetcher.fetch(UserConfig.selectedAccount, categoriesType, (emojiGroups) -> { if (emojiGroups != null) { - categories = new EmojiCategory[(additionalCategories == null ? 0 : additionalCategories.length) + emojiGroups.groups.size()]; - int i = 0; - if (additionalCategories != null) { - for (; i < additionalCategories.length; ++i) { - categories[i] = additionalCategories[i]; + Runnable action = () -> { + categories = new EmojiCategory[(additionalCategories == null ? 0 : additionalCategories.length) + emojiGroups.groups.size()]; + int i = 0; + if (additionalCategories != null) { + for (; i < additionalCategories.length; ++i) { + categories[i] = additionalCategories[i]; + } } - } - for (int j = 0; j < emojiGroups.groups.size(); ++j) { - categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j)); - } - adapter.notifyDataSetChanged(); - setCategoriesShownT(0); - updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16); + for (int j = 0; j < emojiGroups.groups.size(); ++j) { + categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j)); + } + adapter.notifyDataSetChanged(); + setCategoriesShownT(0); + updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16); + }; + NotificationCenter.getInstance(UserConfig.selectedAccount).doOnIdle(action); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java index 171c6c4d3..c1b3e0392 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java @@ -160,7 +160,6 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.playerDidStartPlaying); } playerCounter++; - //Log.d("kek", "playerCounter " + playerCounter); } @Override @@ -343,7 +342,6 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.playerDidStartPlaying); } playerCounter--; - //Log.d("kek", "playerCounter " + playerCounter); } @Override 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 6a5ae2f15..fc1ac7efa 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 @@ -7,6 +7,7 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Shader; +import android.os.Process; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DispatchQueue; @@ -25,7 +26,7 @@ public class SpoilerEffectBitmapFactory { return factory; } - final DispatchQueue dispatchQueue = new DispatchQueue("SpoilerEffectBitmapFactory"); + final DispatchQueue dispatchQueue = new DispatchQueue("SpoilerEffectBitmapFactory", true, 3 * Process.THREAD_PRIORITY_LESS_FAVORABLE); private Bitmap shaderBitmap; Bitmap bufferBitmap; Bitmap backgroundBitmap; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 31c206ce5..f202cb469 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -2086,10 +2086,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. int currentPosition = layoutManager.findFirstVisibleItemPosition(); if (currentPosition == 0) { int pTop = getPaddingTop(); - View view = findArchiveDialogCell(parentPage); - int height = (int) (AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) * PullForegroundDrawable.SNAP_HEIGHT); - int diff = (view.getTop() - pTop) + view.getMeasuredHeight(); - if (view instanceof DialogCell) { + DialogCell view = findArchiveDialogCell(parentPage); + if (view != null) { + int height = (int) (AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) * PullForegroundDrawable.SNAP_HEIGHT); + int diff = (view.getTop() - pTop) + view.getMeasuredHeight(); + long pullingTime = System.currentTimeMillis() - startArchivePullingTime; if (diff < height || pullingTime < PullForegroundDrawable.minPullingTime) { disableActionBarScrolling = true; @@ -2941,6 +2942,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); ((SizeNotifierFrameLayout) fragmentView).invalidateBlur(); + if (optionsItem != null) { + optionsItem.setVisibility(View.GONE); + } } @Override @@ -2990,12 +2994,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); ((SizeNotifierFrameLayout) fragmentView).invalidateBlur(); + if (optionsItem != null) { + optionsItem.setVisibility(View.VISIBLE); + } } @Override public void onTextChanged(EditText editText) { String text = editText.getText().toString(); - if (text.length() != 0 || (searchViewPager.dialogsSearchAdapter != null && searchViewPager.dialogsSearchAdapter.hasRecentSearch()) || searchFiltersWasShowed) { + if (text.length() != 0 || (searchViewPager.dialogsSearchAdapter != null && searchViewPager.dialogsSearchAdapter.hasRecentSearch()) || searchFiltersWasShowed || hasStories) { searchWas = true; if (!searchIsShowed) { showSearch(true, false, true); @@ -3024,7 +3031,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searchItem.setVisibility(View.GONE); } if (isArchive()) { - searchItem.searchRightMargin = -44; optionsItem = menu.addItem(4, R.drawable.ic_ab_other); optionsItem.addSubItem(5, R.drawable.msg_customize, LocaleController.getString("ArchiveSettings")).setColors(getThemedColor(Theme.key_actionBarDefaultSubmenuItem), getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); optionsItem.addSubItem(6, R.drawable.msg_help, LocaleController.getString("HowDoesItWork")).setColors(getThemedColor(Theme.key_actionBarDefaultSubmenuItem), getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); @@ -3271,7 +3277,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (initialDialogsType != DIALOGS_TYPE_DEFAULT) { return false; } - if (actionBar.isActionModeShowed()) { + if (actionBar.isActionModeShowed() || storiesOverscroll != 0) { return false; } if (filterOptions != null && filterOptions.isShown()) { @@ -4844,7 +4850,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }, subItem -> { subItem.setMultiline(false); }) - .addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchiveStories", R.string.ArchiveStories), () -> { + .addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), () -> { toggleArciveForStory(dialogId); }, subItem -> { subItem.setMultiline(false); @@ -6750,10 +6756,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (searchFiltersWasShowed) { onlyDialogsAdapter = false; } else { - onlyDialogsAdapter = onlyDialogsAdapter() && !hasStories; + onlyDialogsAdapter = onlyDialogsAdapter(); } searchViewPager.showOnlyDialogsAdapter(onlyDialogsAdapter); - whiteActionBar = !onlyDialogsAdapter; + whiteActionBar = !onlyDialogsAdapter || hasStories; if (whiteActionBar) { searchFiltersWasShowed = true; } @@ -7048,7 +7054,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. public boolean onlyDialogsAdapter() { int dialogsCount = getMessagesController().getTotalDialogsCount(); - return onlySelect || !searchViewPager.dialogsSearchAdapter.hasRecentSearch() || dialogsCount <= 10; + return onlySelect || !searchViewPager.dialogsSearchAdapter.hasRecentSearch() || dialogsCount <= 10 && !hasStories; } private void updateFilterTabsVisibility(boolean animated) { @@ -8053,6 +8059,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. this.storiesEnabled = storiesEnabled; } + if (floatingButton == null || floatingButtonContainer == null) { + return; + } + if (initialDialogsType == DIALOGS_TYPE_WIDGET) { floatingButton.setImageResource(R.drawable.floating_check); floatingButtonContainer.setContentDescription(LocaleController.getString("Done", R.string.Done)); @@ -11802,7 +11812,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (StoryRecorder.isVisible() || (storyViewer != null && storyViewer.isFullyVisible())) { animated = false; } - boolean onlySelfStories = getStoriesController().hasOnlySelfStories(); + boolean onlySelfStories = !isArchive() && getStoriesController().hasOnlySelfStories(); boolean newVisibility; if (isArchive()) { newVisibility = !getStoriesController().getHiddenList().isEmpty(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index 3085a6641..7a6c60f28 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -12,6 +12,7 @@ import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.SpannableStringBuilder; +import android.text.TextPaint; import android.text.TextUtils; import android.util.SparseArray; import android.view.Gravity; @@ -116,7 +117,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente private String currentDataQuery; - private static SpannableStringBuilder arrowSpan; + private static SpannableStringBuilder[] arrowSpan = new SpannableStringBuilder[3]; private int photoViewerClassGuid; @@ -246,7 +247,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente @Override public CharSequence getTitleFor(int i) { - return createFromInfoString(messages.get(i)); + return createFromInfoString(messages.get(i), 0); } @Override @@ -422,20 +423,37 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente emptyView.setVisibility(View.GONE); } - public static CharSequence createFromInfoString(MessageObject messageObject) { - return createFromInfoString(messageObject, true); + public static CharSequence createFromInfoString(MessageObject messageObject, int arrowType) { + return createFromInfoString(messageObject, true, arrowType); } - public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat) { + public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat, int arrowType) { + return createFromInfoString(messageObject, includeChat, arrowType, null); + } + + public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat, int arrowType, TextPaint textPaint) { if (messageObject == null) { return ""; } - if (arrowSpan == null) { - arrowSpan = new SpannableStringBuilder(">"); - Drawable arrowDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.attach_arrow_right).mutate(); - ColoredImageSpan span = new ColoredImageSpan(arrowDrawable, ColoredImageSpan.ALIGN_CENTER); - arrowDrawable.setBounds(0, AndroidUtilities.dp(1), AndroidUtilities.dp(13), AndroidUtilities.dp(1 + 13)); - arrowSpan.setSpan(span, 0, arrowSpan.length(), 0); + if (arrowSpan[arrowType] == null) { + arrowSpan[arrowType] = new SpannableStringBuilder(">"); + int resId; + if (arrowType == 0) { + resId = R.drawable.attach_arrow_right; + } else if (arrowType == 1) { + resId = R.drawable.msg_mini_arrow_mediathin; + } else if (arrowType == 2) { + resId = R.drawable.msg_mini_arrow_mediabold; + } else { + return ""; + } + Drawable arrowDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, resId).mutate(); + ColoredImageSpan span = new ColoredImageSpan(arrowDrawable, arrowType == 0 ? ColoredImageSpan.ALIGN_CENTER : ColoredImageSpan.ALIGN_BASELINE); +// arrowDrawable.setBounds(0, 0, AndroidUtilities.dp(13), AndroidUtilities.dp(13)); + if (arrowType == 1 || arrowType == 2) { + span.setScale(.85f); + } + arrowSpan[arrowType].setSpan(span, 0, arrowSpan[arrowType].length(), 0); } CharSequence fromName = null; TLRPC.User user = messageObject.messageOwner.from_id.user_id != 0 ? MessagesController.getInstance(UserConfig.selectedAccount).getUser(messageObject.messageOwner.from_id.user_id) : null; @@ -459,17 +477,17 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente chatTitle = ForumUtilities.getTopicSpannedName(topic, null); } } - chatTitle = Emoji.replaceEmoji(chatTitle, null, AndroidUtilities.dp(12), false); + chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false); SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); spannableStringBuilder - .append(Emoji.replaceEmoji(UserObject.getFirstName(user), null, AndroidUtilities.dp(12), false)) + .append(Emoji.replaceEmoji(UserObject.getFirstName(user), textPaint == null ? null : textPaint.getFontMetricsInt(), false)) .append(' ') - .append(arrowSpan) + .append(arrowSpan[arrowType]) .append(' ') .append(chatTitle); fromName = spannableStringBuilder; } else if (user != null) { - fromName = Emoji.replaceEmoji(UserObject.getUserName(user), null, AndroidUtilities.dp(12), false); + fromName = Emoji.replaceEmoji(UserObject.getUserName(user), textPaint == null ? null : textPaint.getFontMetricsInt(), false); } else if (chatFrom != null) { CharSequence chatTitle = chatFrom.title; if (ChatObject.isForum(chatFrom)) { @@ -478,7 +496,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente chatTitle = ForumUtilities.getTopicSpannedName(topic, null); } } - chatTitle = Emoji.replaceEmoji(chatTitle, null, AndroidUtilities.dp(12), false); + chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false); fromName = chatTitle; } return fromName == null ? "" : fromName; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index c50f477ad..01cd22e16 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -3630,7 +3630,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (baseFragment != null) { storyItem.dialogId = peerId; StoryViewer storyViewer = baseFragment.getOrCreateStoryViewer(); - if (storyViewer.isShown()) { + if (storyViewer.isShown() && storyViewer.attachedToParent()) { StoryViewer overlayStoryViewer = baseFragment.getOrCreateOverlayStoryViewer(); final StoryViewer storyViewer1 = storyViewer; overlayStoryViewer.setOnCloseListener(() -> storyViewer1.setOverlayVisible(false)); @@ -5693,7 +5693,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati super.onDestroy(); onFinish(); FloatingDebugController.onDestroy(); - flagSecureReason.detach(); + if (flagSecureReason != null) { + flagSecureReason.detach(); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index f9f108c05..9d5355e1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -12067,7 +12067,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat newMessageObject.updateTranslation(); isVideo = newMessageObject.isVideo(); - title = FilteredSearchView.createFromInfoString(newMessageObject, opennedFromMedia && !openedFromProfile); + title = FilteredSearchView.createFromInfoString(newMessageObject, opennedFromMedia && !openedFromProfile, 0); CharSequence subtitle = null; if (newMessageObject.messageOwner != null) { subtitle = LocaleController.formatDateAudio(newMessageObject.messageOwner.date, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 58a54b387..d9bfd134d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -191,6 +191,7 @@ import org.telegram.ui.Components.InstantCameraView; import org.telegram.ui.Components.ItemOptions; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.Paint.PersistColorPalette; import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumGradient; @@ -3453,6 +3454,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ChatThemeController.getInstance(currentAccount).clearCache(); getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); RestrictedLanguagesSelectActivity.cleanup(); + PersistColorPalette.getInstance(currentAccount).cleanup(); } else if (which == 7) { VoIPHelper.showCallDebugSettings(getParentActivity()); } else if (which == 8) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index 4a0e6bf5f..32e7c5c85 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -110,6 +110,7 @@ import org.telegram.ui.Components.Premium.PremiumButtonView; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumLockIconView; import org.telegram.ui.Components.RLottieImageView; +import org.telegram.ui.Components.Reactions.HwEmojis; import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; @@ -339,12 +340,13 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private View backgroundView; private EmojiTabsStrip[] cachedEmojiTabs = new EmojiTabsStrip[2]; public EmojiTabsStrip emojiTabs; - private View emojiTabsShadow; - private SearchBox searchBox; + public View emojiTabsShadow; + public SearchBox searchBox; public FrameLayout gridViewContainer; public EmojiListView emojiGridView; public EmojiListView emojiSearchGridView; public FrameLayout emojiSearchEmptyView; + public FrameLayout emojiGridViewContainer; private BackupImageView emojiSearchEmptyViewImageView; private View bubble1View; private View bubble2View; @@ -443,9 +445,24 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati addView(bubble1View, LayoutHelper.createFrame(10, 10, Gravity.TOP | Gravity.LEFT, bubbleX / AndroidUtilities.density + (bubbleRight ? -12 : 4), topMarginDp, 0, 0)); } + backgroundView = new View(context) { + + @Override + protected void onDraw(Canvas canvas) { + if (!drawBackground) { + super.dispatchDraw(canvas); + return; + } + canvas.drawColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider)); + } + }; + + boolean needBackgroundShadow = type == TYPE_TOPIC_ICON || type == TYPE_AVATAR_CONSTRUCTOR; + contentView = new FrameLayout(context) { - private Path path = new Path(); - private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path pathApi20 = new Path(); + private final Paint paintApi20 = new Paint(Paint.ANTI_ALIAS_FLAG); + private final boolean beforeLollipop = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; @Override protected void dispatchDraw(Canvas canvas) { @@ -453,36 +470,68 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati super.dispatchDraw(canvas); return; } - canvas.save(); - Theme.applyDefaultShadow(paint); - paint.setColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider)); - paint.setAlpha((int) (255 * getAlpha())); - float px = (bubbleX == null ? getWidth() / 2f : bubbleX) + AndroidUtilities.dp(20); - float w = getWidth() - getPaddingLeft() - getPaddingRight(); - float h = getHeight() - getPaddingBottom() - getPaddingTop(); - AndroidUtilities.rectTmp.set( - getPaddingLeft() + (px - px * scaleX), - getPaddingTop(), - getPaddingLeft() + px + (w - px) * scaleX, - getPaddingTop() + h * scaleY - ); - path.rewind(); - path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(12), AndroidUtilities.dp(12), Path.Direction.CW); - canvas.drawPath(path, paint); -// if (enterAnimationInProgress() { - canvas.clipPath(path); -// } - super.dispatchDraw(canvas); - canvas.restore(); + if (beforeLollipop) { + canvas.save(); + if (needBackgroundShadow) { + Theme.applyDefaultShadow(paintApi20); + } + paintApi20.setColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider)); + paintApi20.setAlpha((int) (255 * getAlpha())); + float px = (bubbleX == null ? getWidth() / 2f : bubbleX) + AndroidUtilities.dp(20); + float w = getWidth() - getPaddingLeft() - getPaddingRight(); + float h = getHeight() - getPaddingBottom() - getPaddingTop(); + AndroidUtilities.rectTmp.set( + getPaddingLeft() + (px - px * scaleX), + getPaddingTop(), + getPaddingLeft() + px + (w - px) * scaleX, + getPaddingTop() + h * scaleY + ); + pathApi20.rewind(); + pathApi20.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(12), AndroidUtilities.dp(12), Path.Direction.CW); + canvas.drawPath(pathApi20, paintApi20); + canvas.clipPath(pathApi20); + super.dispatchDraw(canvas); + canvas.restore(); + } else { + super.dispatchDraw(canvas); + } } }; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + contentView.setOutlineProvider(new ViewOutlineProvider() { + private final Rect rect = new Rect(); + + @Override + public void getOutline(View view, Outline outline) { + float px = (bubbleX == null ? view.getWidth() / 2f : bubbleX) + AndroidUtilities.dp(20); + float w = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight(); + float h = view.getHeight() - view.getPaddingBottom() - view.getPaddingTop(); + rect.set( + (int) (view.getPaddingLeft() + (px - px * scaleX)), + view.getPaddingTop(), + (int) (view.getPaddingLeft() + px + (w - px) * scaleX), + (int) (view.getPaddingTop() + h * scaleY) + ); + outline.setRoundRect(rect, dp(12)); + } + }); + contentView.setClipToOutline(true); + if (needBackgroundShadow) { + contentView.setElevation(2f); + } + } + if (type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION) { contentView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); } + + contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION ? 6 + topMarginDp : 0, 0, 0)); if (bubbleX != null) { bubble2View = new View(context) { + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -576,6 +625,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati cachedEmojiTabs[1].setVisibility(View.GONE); emojiTabsShadow = new View(context) { + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -663,7 +713,59 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) + AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); } }; - gridViewContainer.addView(emojiGridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 0)); + + emojiGridViewContainer = new FrameLayout(context) { + private final Rect rect = new Rect(); + + /** + * The child does not redraw and uses hardware acceleration during animation. + * We simply display the pieces we need from a large image for cascade animation. + */ + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == emojiGridView && HwEmojis.isHwEnabled() && HwEmojis.isCascade()) { + for (int i = 0; i < emojiGridView.getChildCount(); i++) { + View view = emojiGridView.getChildAt(i); + if (view instanceof ImageViewEmoji) { + ImageViewEmoji viewEmoji = (ImageViewEmoji) view; + if (viewEmoji.getAnimatedScale() == 1f) { + rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); + canvas.save(); + canvas.clipRect(rect); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + } else if (viewEmoji.getAnimatedScale() > 0f) { + rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); + rect.set( + (int) (rect.centerX() - rect.width() / 2f * viewEmoji.getAnimatedScale()), + (int) (rect.centerY() - rect.height() / 2f * viewEmoji.getAnimatedScale()), + (int) (rect.centerX() + rect.width() / 2f * viewEmoji.getAnimatedScale()), + (int) (rect.centerY() + rect.height() / 2f * viewEmoji.getAnimatedScale()) + ); + canvas.save(); + canvas.clipRect(rect); + canvas.scale(viewEmoji.getAnimatedScale(), viewEmoji.getAnimatedScale(), rect.centerX(), rect.centerY()); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + } + } else if (view instanceof TextView || view instanceof EmojiPackExpand || view instanceof EmojiPackButton || view instanceof HeaderView) { + rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); + canvas.save(); + canvas.clipRect(rect); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + } + } + + return false; + } + + return super.drawChild(canvas, child, drawingTime); + } + }; + + emojiGridViewContainer.addView(emojiGridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 0)); + gridViewContainer.addView(emojiGridViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 0)); emojiSearchGridView = new EmojiListView(context) { @Override @@ -746,7 +848,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } }); scrollHelper.setScrollListener(() -> { - invalidateParent(); + invalidateParent(); }); RecyclerListView.OnItemLongClickListenerExtended onItemLongClick = new RecyclerListView.OnItemLongClickListenerExtended() { @@ -904,7 +1006,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } }; - searchBox.setTranslationY(-AndroidUtilities.dp( 52)); + searchBox.setTranslationY(-AndroidUtilities.dp(52)); searchBox.setVisibility(View.INVISIBLE); gridViewContainer.addView(searchBox, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 52, Gravity.TOP, 0, -4, 0, 0)); @@ -926,7 +1028,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati bottomGradientView = new View(context); Drawable bottomGradient = getResources().getDrawable(R.drawable.gradient_bottom); bottomGradient.setColorFilter(new PorterDuffColorFilter(AndroidUtilities.multiplyAlphaComponent(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider), .8f), PorterDuff.Mode.SRC_IN)); - // bottomGradientView.setBackground(bottomGradient); + // bottomGradientView.setBackground(bottomGradient); bottomGradientView.setAlpha(0); contentView.addView(bottomGradientView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); @@ -939,6 +1041,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati bigReactionImageReceiver.setLayerNum(7); + if (isAnimatedShow()) { + HwEmojis.beforePreparing(); + } updateRows(true, false); } @@ -1120,16 +1225,16 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati drawableToBounds = new Rect(); } drawableToBounds.set( - (int) (bounds.centerX() - bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), - (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? (bounds.height() * .81f + 1) : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp) - bounds.height() * scale), - (int) (bounds.centerX() + bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), - (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? bounds.height() * .81f + 1 : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp)) + (int) (bounds.centerX() - bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), + (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? (bounds.height() * .81f + 1) : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp) - bounds.height() * scale), + (int) (bounds.centerX() + bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), + (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? bounds.height() * .81f + 1 : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp)) ); scrimDrawable.setBounds( - drawableToBounds.left, - drawableToBounds.top, - (int) (drawableToBounds.left + drawableToBounds.width() / scale), - (int) (drawableToBounds.top + drawableToBounds.height() / scale) + drawableToBounds.left, + drawableToBounds.top, + (int) (drawableToBounds.left + drawableToBounds.width() / scale), + (int) (drawableToBounds.top + drawableToBounds.height() / scale) ); canvas.scale(scale, scale, drawableToBounds.left, drawableToBounds.top); scrimDrawable.draw(canvas); @@ -1150,6 +1255,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private ValueAnimator emojiSelectAnimator; + public void animateEmojiSelect(ImageViewEmoji view, Runnable onDone) { if (emojiSelectAnimator != null || scrimDrawable == null) { onDone.run(); @@ -1159,16 +1265,16 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati view.notDraw = true; final Rect from = new Rect(); from.set( - contentView.getLeft() + emojiGridView.getLeft() + view.getLeft(), - contentView.getTop() + emojiGridView.getTop() + view.getTop(), - contentView.getLeft() + emojiGridView.getLeft() + view.getRight(), - contentView.getTop() + emojiGridView.getTop() + view.getBottom() + contentView.getLeft() + emojiGridView.getLeft() + view.getLeft(), + contentView.getTop() + emojiGridView.getTop() + view.getTop(), + contentView.getLeft() + emojiGridView.getLeft() + view.getRight(), + contentView.getTop() + emojiGridView.getTop() + view.getBottom() ); final AnimatedEmojiDrawable statusDrawable = - view.drawable instanceof AnimatedEmojiDrawable ? - AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_EMOJI_STATUS, ((AnimatedEmojiDrawable) view.drawable).getDocumentId()) : - null; + view.drawable instanceof AnimatedEmojiDrawable ? + AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_EMOJI_STATUS, ((AnimatedEmojiDrawable) view.drawable).getDocumentId()) : + null; emojiSelectView = view; emojiSelectRect = new Rect(); @@ -1183,10 +1289,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati AndroidUtilities.lerp(from, drawableToBounds, t, emojiSelectRect); float scale = Math.max(1, overshootInterpolator.getInterpolation(MathUtils.clamp(3 * t - (3 - 1), 0, 1f))) * view.getScaleX(); emojiSelectRect.set( - (int) (emojiSelectRect.centerX() - emojiSelectRect.width() / 2f * scale), - (int) (emojiSelectRect.centerY() - emojiSelectRect.height() / 2f * scale), - (int) (emojiSelectRect.centerX() + emojiSelectRect.width() / 2f * scale), - (int) (emojiSelectRect.centerY() + emojiSelectRect.height() / 2f * scale) + (int) (emojiSelectRect.centerX() - emojiSelectRect.width() / 2f * scale), + (int) (emojiSelectRect.centerY() - emojiSelectRect.height() / 2f * scale), + (int) (emojiSelectRect.centerX() + emojiSelectRect.width() / 2f * scale), + (int) (emojiSelectRect.centerY() + emojiSelectRect.height() / 2f * scale) ); invalidate(); @@ -1266,6 +1372,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private boolean gridSearch = false; + public void switchGrids(boolean search, boolean liftUp) { if (gridSearch == search) { return; @@ -1308,11 +1415,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati gridSwitchAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); gridSwitchAnimator.start(); ((View) emojiGridView.getParent()).animate() - .translationY(gridSearch && liftUp ? -AndroidUtilities.dp(36) : 0) - .setUpdateListener(anm -> invalidateParent()) - .setInterpolator(CubicBezierInterpolator.DEFAULT) - .setDuration(160) - .start(); + .translationY(gridSearch && liftUp ? -AndroidUtilities.dp(36) : 0) + .setUpdateListener(anm -> invalidateParent()) + .setInterpolator(CubicBezierInterpolator.DEFAULT) + .setDuration(160) + .start(); if (gridSearch && liftUp) { emojiSearchGridView.setPadding(dp(5), dp(52 + 2), dp(5), dp(2)); } else { @@ -1401,6 +1508,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private boolean searchEmptyViewVisible = false; private ValueAnimator searchEmptyViewAnimator; + public void switchSearchEmptyView(boolean empty) { if (searchEmptyViewVisible == empty) { return; @@ -1735,7 +1843,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati return VIEW_TYPE_EMOJI; } if (position > emojiStartRow && position - emojiStartRow - 1 < searchResult.size()) { - if (searchResult.get(position - emojiStartRow - 1 ).documentId != 0) { + if (searchResult.get(position - emojiStartRow - 1).documentId != 0) { return VIEW_TYPE_EMOJI; } } @@ -1911,8 +2019,8 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati // } // }, false).dispatchUpdatesTo(SearchAdapter.this); // } else { - this.notifyDataSetChanged(); - // } + this.notifyDataSetChanged(); + // } switchSearchEmptyView(searched && count == 0); } @@ -1935,10 +2043,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public boolean isEnabled(RecyclerView.ViewHolder holder) { int viewType = holder.getItemViewType(); return ( - viewType == VIEW_TYPE_IMAGE || - viewType == VIEW_TYPE_REACTION || - viewType == VIEW_TYPE_EMOJI || - viewType == VIEW_TYPE_TOPIC_ICON + viewType == VIEW_TYPE_IMAGE || + viewType == VIEW_TYPE_REACTION || + viewType == VIEW_TYPE_EMOJI || + viewType == VIEW_TYPE_TOPIC_ICON ); } @@ -2009,7 +2117,8 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati return VIEW_TYPE_HINT; } else if (positionToSection.indexOfKey(position) >= 0 || position == recentReactionsSectionRow || position == popularSectionRow || position == topicEmojiHeaderRow) { return VIEW_TYPE_HEADER; - } if (position == defaultTopicIconRow) { + } + if (position == defaultTopicIconRow) { return VIEW_TYPE_TOPIC_ICON; } else { if (showStickers) { @@ -2266,7 +2375,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati TLRPC.Document document = pack.documents.get(position - startPosition - 1); if (document != null) { if (showStickers) { - imageView.setSticker(document, emojiSearchGridView); + imageView.setSticker(document, emojiSearchGridView); } else { imageView.isStaticIcon = false; if (imageView.imageReceiver != null) { @@ -2399,7 +2508,23 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public EmojiPackButton(Context context) { super(context); - addButtonTextView = new AnimatedTextView(getContext()); + addButtonTextView = new AnimatedTextView(getContext()) { + @Override + public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } + }; addButtonTextView.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT); addButtonTextView.setTextSize(AndroidUtilities.dp(14)); addButtonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -2575,13 +2700,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public int skewIndex; public boolean isStaticIcon; private float selectedProgress; + private float animatedScale = 1f; - final AnimatedEmojiSpan.InvalidateHolder invalidateHolder = new AnimatedEmojiSpan.InvalidateHolder() { - @Override - public void invalidate() { - if (getParent() != null) { - ((View)getParent()).invalidate(); - } + final AnimatedEmojiSpan.InvalidateHolder invalidateHolder = () -> { + if (HwEmojis.isHwEnabled()) { + return; + } + if (getParent() != null) { + ((View) getParent()).invalidate(); } }; @@ -2590,6 +2716,17 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati preloadEffectImageReceiver.ignoreNotifications = true; } + /** + * {@link View#setScaleX} causes an implicit redraw of the parent. Therefore, we use a custom method. + */ + public void setAnimatedScale(float scale) { + animatedScale = scale; + } + + public float getAnimatedScale() { + return animatedScale; + } + @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY)); @@ -2656,11 +2793,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public void drawSelected(Canvas canvas, View view) { if ((selected || selectedProgress > 0) && !notDraw) { if (selected && selectedProgress < 1f) { - selectedProgress += 16/ 300f; + selectedProgress += 16 / 300f; view.invalidate(); } if (!selected && selectedProgress > 0) { - selectedProgress -= 16/ 300f; + selectedProgress -= 16 / 300f; view.invalidate(); } selectedProgress = Utilities.clamp(selectedProgress, 1f, 0f); @@ -2718,7 +2855,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati ((AnimatedEmojiDrawable) drawable).addView(invalidateHolder); } } - } public void setSticker(TLRPC.Document document, View parent) { @@ -2743,15 +2879,26 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati @Override public void invalidate() { + if (HwEmojis.isHwEnabled()) { + return; + } if (getParent() != null) { ((View) getParent()).invalidate(); } } + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.isHwEnabled()) { + return; + } + super.invalidate(l, t, r, b); + } + public void createPremiumLockView() { if (premiumLockIconView == null) { premiumLockIconView = new PremiumLockIconView(getContext(), PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED); - int measureSpec = MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12),MeasureSpec.EXACTLY); + int measureSpec = MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12), MeasureSpec.EXACTLY); premiumLockIconView.measure(measureSpec, measureSpec); premiumLockIconView.layout(0, 0, premiumLockIconView.getMeasuredWidth(), premiumLockIconView.getMeasuredHeight()); } @@ -2788,7 +2935,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (type == TYPE_SET_DEFAULT_REACTION) { return; } - final String key = "emoji" + (type==TYPE_EMOJI_STATUS ? "status" : "reaction") + "usehint"; + final String key = "emoji" + (type == TYPE_EMOJI_STATUS ? "status" : "reaction") + "usehint"; final int value = MessagesController.getGlobalMainSettings().getInt(key, 0); if (value <= 3) { MessagesController.getGlobalMainSettings().edit().putInt(key, value + 1).apply(); @@ -2895,7 +3042,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati totalCount++; } } else { - TLRPC.TL_emojiList emojiList = forUser ? MediaDataController.getInstance(currentAccount). profileAvatarConstructorDefault : MediaDataController.getInstance(currentAccount).groupAvatarConstructorDefault; + TLRPC.TL_emojiList emojiList = forUser ? MediaDataController.getInstance(currentAccount).profileAvatarConstructorDefault : MediaDataController.getInstance(currentAccount).groupAvatarConstructorDefault; if (emojiList != null && emojiList.document_id != null && !emojiList.document_id.isEmpty()) { for (int i = 0; i < emojiList.document_id.size(); ++i) { recent.add(new AnimatedEmojiSpan(emojiList.document_id.get(i), null)); @@ -3371,7 +3518,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati imageViewEmoji.updatePressedProgress(); int top = smoothScrolling ? (int) child.getY() : child.getTop(); ArrayList arrayList = viewsGroupedByLines.get(top); - canvas.save(); canvas.translate(imageViewEmoji.getX(), imageViewEmoji.getY()); imageViewEmoji.drawSelected(canvas, this); @@ -3475,8 +3621,8 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (imageViewEmoji.premiumLockIconView != null && imageViewEmoji.premiumLockIconView.getVisibility() == View.VISIBLE) { canvas.save(); canvas.translate( - (int) (imageViewEmoji.getX() + imageViewEmoji.getMeasuredWidth() - imageViewEmoji.premiumLockIconView.getMeasuredWidth()), - (int) (imageViewEmoji.getY() + imageViewEmoji.getMeasuredHeight() - imageViewEmoji.premiumLockIconView.getMeasuredHeight()) + (int) (imageViewEmoji.getX() + imageViewEmoji.getMeasuredWidth() - imageViewEmoji.premiumLockIconView.getMeasuredWidth()), + (int) (imageViewEmoji.getY() + imageViewEmoji.getMeasuredHeight() - imageViewEmoji.premiumLockIconView.getMeasuredHeight()) ); imageViewEmoji.premiumLockIconView.draw(canvas); canvas.restore(); @@ -3490,6 +3636,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } canvas.restoreToCount(restoreTo); + HwEmojis.exec(); } public class DrawingInBackgroundLine extends DrawingInBackgroundThreadDrawable { @@ -3528,7 +3675,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } } - if (drawInUi) { + + if (HwEmojis.isHwEnabled()) { + alpha = 1f; + } + if (drawInUi || HwEmojis.isPreparing()) { prepareDraw(System.currentTimeMillis()); drawInUiThread(canvas, alpha); reset(); @@ -3572,7 +3723,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati // // canvas.drawBitmapMesh(bitmap, 3, 1, verts, 0, null, 0, paint); // } else { - canvas.drawBitmap(bitmap, 0, 0, paint); + canvas.drawBitmap(bitmap, 0, 0, paint); // } } @@ -3675,10 +3826,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati AndroidUtilities.rectTmp2.set(imageView.getPaddingLeft(), imageView.getPaddingTop(), imageView.getWidth() - imageView.getPaddingRight(), imageView.getHeight() - imageView.getPaddingBottom()); if (imageView.selected && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR) { AndroidUtilities.rectTmp2.set( - (int) Math.round(AndroidUtilities.rectTmp2.centerX() - AndroidUtilities.rectTmp2.width() / 2f * 0.86f), - (int) Math.round(AndroidUtilities.rectTmp2.centerY() - AndroidUtilities.rectTmp2.height() / 2f * 0.86f), - (int) Math.round(AndroidUtilities.rectTmp2.centerX() + AndroidUtilities.rectTmp2.width() / 2f * 0.86f), - (int) Math.round(AndroidUtilities.rectTmp2.centerY() + AndroidUtilities.rectTmp2.height() / 2f * 0.86f) + (int) Math.round(AndroidUtilities.rectTmp2.centerX() - AndroidUtilities.rectTmp2.width() / 2f * 0.86f), + (int) Math.round(AndroidUtilities.rectTmp2.centerY() - AndroidUtilities.rectTmp2.height() / 2f * 0.86f), + (int) Math.round(AndroidUtilities.rectTmp2.centerX() + AndroidUtilities.rectTmp2.width() / 2f * 0.86f), + (int) Math.round(AndroidUtilities.rectTmp2.centerY() + AndroidUtilities.rectTmp2.height() / 2f * 0.86f) ); } AndroidUtilities.rectTmp2.offset(imageView.getLeft() + (int) imageView.getTranslationX() - startOffset, topOffset); @@ -3773,7 +3924,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati imageView.skewIndex = i; if (scale != 1 || skewAlpha < 1) { canvas.save(); - canvas.scale(scale, scale, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); + if (imageView.selected && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR) { + //scale here only selected emoji + canvas.scale(0.85f, 0.85f, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); + } skew(canvas, i, imageView.getHeight()); drawImage(canvas, drawable, imageView, alpha); canvas.restore(); @@ -3851,14 +4005,33 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati lineDrawables.clear(); } + @Override + public void invalidateViews() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidateViews(); + } + @Override public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } if (invalidated) { return; } invalidated = true; super.invalidate(); } + + @Override + public void invalidate(int l, int t, int r, int b) { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(l, t, r, b); + } } @Override @@ -3916,6 +4089,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } + private static boolean isFirstOpen = true; private Runnable dismiss; final float durationScale = 1f; final long showDuration = (long) (800 * durationScale); @@ -3923,6 +4097,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private ValueAnimator hideAnimator; private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(); + private boolean isAnimatedShow() { + return type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR; + } + public void onShow(Runnable dismiss) { if (listStateId != null) { Parcelable state = listStates.get(listStateId); @@ -3949,17 +4127,32 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati hideAnimator.cancel(); hideAnimator = null; } - boolean animated = type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR; + boolean animated = isAnimatedShow(); if (animated) { - showAnimator = ValueAnimator.ofFloat(0, 1); + showAnimator = ValueAnimator.ofFloat(0f, 1f); showAnimator.addUpdateListener(anm -> { final float t = (float) anm.getAnimatedValue(); updateShow(t); }); + showAnimator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { + HwEmojis.disableHw(); + emojiGridView.setLayerType(LAYER_TYPE_NONE, null); + searchBox.setLayerType(LAYER_TYPE_NONE, null); + emojiTabsShadow.setLayerType(LAYER_TYPE_NONE, null); + backgroundView.setLayerType(LAYER_TYPE_NONE, null); + if (bubble2View != null) { + bubble2View.setLayerType(LAYER_TYPE_NONE, null); + } + if (bubble1View != null) { + bubble1View.setLayerType(LAYER_TYPE_NONE, null); + } + searchBox.checkInitialization(); + emojiTabs.showRecentTabStub(false); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); notificationsLocker.unlock(); AndroidUtilities.runOnUIThread(NotificationCenter.getGlobalInstance()::runDelayedNotifications); @@ -3976,22 +4169,48 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati child.setScaleY(1); } emojiTabs.contentView.invalidate(); + emojiGridViewContainer.invalidate(); + emojiGridView.invalidate(); } }); - updateShow(0); - showAnimator.setDuration(showDuration); + + if (isFirstOpen) { + isFirstOpen = false; + AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).setUiDbCallback(() -> { + HwEmojis.enableHw(); + AndroidUtilities.runOnUIThread(() -> showAnimator.start(), 0); + }); + HwEmojis.prepare(null, true); + } else { + Runnable action = () -> { + HwEmojis.enableHw(); + AndroidUtilities.runOnUIThread(() -> showAnimator.start(), 0); + }; + HwEmojis.prepare(action, true); + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); notificationsLocker.lock(); - showAnimator.start(); + showAnimator.setDuration(showDuration); + emojiGridView.setLayerType(LAYER_TYPE_HARDWARE, null); + searchBox.setLayerType(LAYER_TYPE_HARDWARE, null); + emojiTabsShadow.setLayerType(LAYER_TYPE_HARDWARE, null); + backgroundView.setLayerType(LAYER_TYPE_HARDWARE, null); + if (bubble2View != null) { + bubble2View.setLayerType(LAYER_TYPE_HARDWARE, null); + } + if (bubble1View != null) { + bubble1View.setLayerType(LAYER_TYPE_HARDWARE, null); + } + emojiTabs.showRecentTabStub(true); + updateShow(0); } else { checkScroll(); updateShow(1); } } - private static boolean firstOpen = true; - - private class SearchBox extends FrameLayout { + public class SearchBox extends FrameLayout { private FrameLayout box; private ImageView search; private ImageView clear; @@ -4092,12 +4311,22 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } super.onFocusChanged(focused, direction, previouslyFocusedRect); } + + @Override + public void invalidate() { + if (HwEmojis.isHwEnabled()) { + return; + } + super.invalidate(); + } }; input.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} + @Override public void afterTextChanged(Editable s) { final String query = input.getText() == null || AndroidUtilities.trim(input.getText(), null).length() == 0 ? null : input.getText().toString(); @@ -4129,7 +4358,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati input.setSingleLine(true); input.setLines(1); input.setTranslationY(AndroidUtilities.dp(-1)); - inputBox.addView(input, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 32, 0)); + inputBox.addView(input, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 32, 0)); if (drawBackground) { inputBoxGradient = new View(context); @@ -4151,7 +4380,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati clear = new ImageView(context); clear.setScaleType(ImageView.ScaleType.CENTER); clear.setImageDrawable(new CloseProgressDrawable2(1.25f) { - { setSide(AndroidUtilities.dp(7)); } + { + setSide(AndroidUtilities.dp(7)); + } + @Override protected int getCurrentColor() { return Theme.getColor(Theme.key_chat_emojiSearchIcon, resourcesProvider); @@ -4171,15 +4403,15 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati showInputBoxGradient(false); }); box.addView(clear, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); - - if (firstOpen) { - AndroidUtilities.runOnUIThread(this::createCategoriesListView, 450); - firstOpen = false; - } else { + if (!HwEmojis.isFirstOpen()) { createCategoriesListView(); } } + public void checkInitialization() { + createCategoriesListView(); + } + private void createCategoriesListView() { if (categoriesListView != null || getContext() == null) { return; @@ -4233,6 +4465,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private Runnable delayedToggle; + private void toggleClear(boolean enabled) { if (enabled) { if (delayedToggle == null) { @@ -4250,6 +4483,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private boolean inputBoxShown = false; + private void showInputBoxGradient(boolean show) { if (show == inputBoxShown) { return; @@ -4298,7 +4532,15 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(8+36+8), MeasureSpec.EXACTLY)); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(8 + 36 + 8), MeasureSpec.EXACTLY)); + } + + @Override + public void invalidate() { + if (HwEmojis.grab(this)) { + return; + } + super.invalidate(); } } @@ -4331,30 +4573,47 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati containery = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(containery); // containeritemst = endslow.getInterpolation(containeritemst); // containeralphat = CubicBezierInterpolator.EASE_OUT.getInterpolation(containeralphat); - contentView.setAlpha(containeralphat); + + backgroundView.setAlpha(containeralphat); + searchBox.setAlpha(containeralphat); + for (int i = 0; i < emojiTabs.contentView.getChildCount(); i++) { + View child = emojiTabs.contentView.getChildAt(i); + child.setAlpha(containeralphat); + } if (scrimDrawable != null) { invalidate(); } - contentView.setTranslationY(AndroidUtilities.dp(-5) * (1f - containeralphat)); + contentView.setTranslationY(dp(-5) * (1f - containeralphat)); if (bubble2View != null) { - bubble2View.setTranslationY(AndroidUtilities.dp(-5) * (1f - containeralphat)); + bubble2View.setTranslationY(dp(-5) * (1f - containeralphat)); } this.scaleX = .15f + .85f * containerx; this.scaleY = .075f + .925f * containery; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + contentView.invalidateOutline(); + } else { + backgroundView.setVisibility(GONE); + contentView.setAlpha(containeralphat); + contentView.invalidate(); + } if (bubble2View != null) { bubble2View.setAlpha(containeralphat); } - contentView.invalidate(); emojiTabsShadow.setAlpha(containeralphat); emojiTabsShadow.setScaleX(Math.min(scaleX, 1)); final float px = emojiTabsShadow.getPivotX(), py = 0; final float fullr = (float) Math.sqrt(Math.max( - px * px + Math.pow(contentView.getHeight(), 2), - Math.pow(contentView.getWidth() - px, 2) + Math.pow(contentView.getHeight(), 2) + px * px + Math.pow(contentView.getHeight(), 2), + Math.pow(contentView.getWidth() - px, 2) + Math.pow(contentView.getHeight(), 2) )); for (int i = 0; i < emojiTabs.contentView.getChildCount(); ++i) { View child = emojiTabs.contentView.getChildAt(i); + if (t == 0) { + child.setLayerType(LAYER_TYPE_HARDWARE, null); + } else if (t == 1) { + child.setLayerType(LAYER_TYPE_NONE, null); + } float ccx = child.getLeft() + child.getWidth() / 2f, ccy = child.getTop() + child.getHeight() / 2f; float distance = (float) Math.sqrt((ccx - px) * (ccx - px) + ccy * ccy * .4f); float scale = AndroidUtilities.cascade(containeritemst, distance, fullr, child.getHeight() * 1.75f); @@ -4364,17 +4623,20 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati child.setScaleX(scale); child.setScaleY(scale); } - emojiTabs.contentView.invalidate(); for (int i = 0; i < emojiGridView.getChildCount(); ++i) { View child = emojiGridView.getChildAt(i); - float cx = child.getLeft() + child.getWidth() / 2f, cy = child.getTop() + child.getHeight() / 2f; - float distance = (float) Math.sqrt((cx - px) * (cx - px) + cy * cy * .2f); - float scale = AndroidUtilities.cascade(containeritemst, distance, fullr, child.getHeight() * 1.75f); - if (Float.isNaN(scale)) - scale = 0; - child.setScaleX(scale); - child.setScaleY(scale); + if (child instanceof ImageViewEmoji) { + ImageViewEmoji imageViewEmoji = (ImageViewEmoji) child; + float cx = child.getLeft() + child.getWidth() / 2f, cy = child.getTop() + child.getHeight() / 2f; + float distance = (float) Math.sqrt((cx - px) * (cx - px) + cy * cy * .2f); + float scale = AndroidUtilities.cascade(containeritemst, distance, fullr, child.getHeight() * 1.75f); + if (Float.isNaN(scale)) { + scale = 0; + } + imageViewEmoji.setAnimatedScale(scale); + } } + emojiGridViewContainer.invalidate(); emojiGridView.invalidate(); } @@ -4422,6 +4684,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public void setDrawBackground(boolean drawBackground) { this.drawBackground = drawBackground; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + contentView.setClipToOutline(drawBackground); + } + if (!drawBackground) { + backgroundView.setVisibility(GONE); + } else { + backgroundView.setVisibility(VISIBLE); + } } public void setRecentReactions(List reactions) { @@ -4473,7 +4743,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } public void setScrimDrawable(AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable scrimDrawable, View drawableParent) { - this.scrimColor = scrimDrawable == null ? 0 : scrimDrawable.getColor(); + this.scrimColor = scrimDrawable == null || scrimDrawable.getColor() == null ? 0 : scrimDrawable.getColor(); this.scrimDrawable = scrimDrawable; this.scrimDrawableParent = drawableParent; if (isAttached && scrimDrawable != null) { @@ -4583,8 +4853,8 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( - MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY) ); } @@ -4613,10 +4883,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati scale *= 0.8f + 0.2f * (1f - (imageViewEmoji.selected ? .7f : imageViewEmoji.pressedProgress)); } AndroidUtilities.rectTmp2.set( - (int) (AndroidUtilities.rectTmp.centerX() - AndroidUtilities.rectTmp.width() / 2 * scale), - (int) (AndroidUtilities.rectTmp.centerY() - AndroidUtilities.rectTmp.height() / 2 * scale), - (int) (AndroidUtilities.rectTmp.centerX() + AndroidUtilities.rectTmp.width() / 2 * scale), - (int) (AndroidUtilities.rectTmp.centerY() + AndroidUtilities.rectTmp.height() / 2 * scale) + (int) (AndroidUtilities.rectTmp.centerX() - AndroidUtilities.rectTmp.width() / 2 * scale), + (int) (AndroidUtilities.rectTmp.centerY() - AndroidUtilities.rectTmp.height() / 2 * scale), + (int) (AndroidUtilities.rectTmp.centerX() + AndroidUtilities.rectTmp.width() / 2 * scale), + (int) (AndroidUtilities.rectTmp.centerY() + AndroidUtilities.rectTmp.height() / 2 * scale) ); float skew = 1f - (1f - imageViewEmoji.skewAlpha) * (1f - showT); canvas.save(); @@ -4703,8 +4973,8 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati this.parentDialogView = parentDialogView; setContentView( - this.contentView = new ContentView(context), - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + this.contentView = new ContentView(context), + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) ); linearLayoutView = new LinearLayout(context); @@ -4716,10 +4986,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati super.onLayout(changed, left, top, right, bottom); getLocationOnScreen(tempLocation); to.set( - tempLocation[0], - tempLocation[1], - tempLocation[0] + getWidth(), - tempLocation[1] + getHeight() + tempLocation[0], + tempLocation[1], + tempLocation[0] + getWidth(), + tempLocation[1] + getHeight() ); AndroidUtilities.lerp(from, to, showT, current); } @@ -4731,32 +5001,32 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati ActionBarMenuItem.addItem(true, false, menuView, 0, LocaleController.getString("SetEmojiStatusUntil1Hour", R.string.SetEmojiStatusUntil1Hour), false, resourcesProvider) - .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 60 * 60))); + .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 60 * 60))); ActionBarMenuItem.addItem(false, false, menuView, 0, LocaleController.getString("SetEmojiStatusUntil2Hours", R.string.SetEmojiStatusUntil2Hours), false, resourcesProvider) - .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 2 * 60 * 60))); + .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 2 * 60 * 60))); ActionBarMenuItem.addItem(false, false, menuView, 0, LocaleController.getString("SetEmojiStatusUntil8Hours", R.string.SetEmojiStatusUntil8Hours), false, resourcesProvider) - .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 8 * 60 * 60))); + .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 8 * 60 * 60))); ActionBarMenuItem.addItem(false, false, menuView, 0, LocaleController.getString("SetEmojiStatusUntil2Days", R.string.SetEmojiStatusUntil2Days), false, resourcesProvider) - .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 2 * 24 * 60 * 60))); + .setOnClickListener(e -> done((int) (System.currentTimeMillis() / 1000 + 2 * 24 * 60 * 60))); ActionBarMenuItem.addItem(false, true, menuView, 0, LocaleController.getString("SetEmojiStatusUntilOther", R.string.SetEmojiStatusUntilOther), false, resourcesProvider) - .setOnClickListener(e -> { - if (dateBottomSheet != null) { - return; - } - boolean[] selected = new boolean[1]; - BottomSheet.Builder builder = AlertsCreator.createStatusUntilDatePickerDialog(context, System.currentTimeMillis() / 1000, date -> { - selected[0] = true; - done(date); - }); - builder.setOnPreDismissListener(di -> { - if (!selected[0]) { - animateMenuShow(true, null); + .setOnClickListener(e -> { + if (dateBottomSheet != null) { + return; } - dateBottomSheet = null; + boolean[] selected = new boolean[1]; + BottomSheet.Builder builder = AlertsCreator.createStatusUntilDatePickerDialog(context, System.currentTimeMillis() / 1000, date -> { + selected[0] = true; + done(date); + }); + builder.setOnPreDismissListener(di -> { + if (!selected[0]) { + animateMenuShow(true, null); + } + dateBottomSheet = null; + }); + dateBottomSheet = builder.show(); + animateMenuShow(false, null); }); - dateBottomSheet = builder.show(); - animateMenuShow(false, null); - }); contentView.addView(linearLayoutView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); @@ -4841,6 +5111,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private boolean done = false; + private void done(Integer date) { if (done) { return; @@ -4931,6 +5202,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private float showT; private boolean showing; private ValueAnimator showAnimator; + private void animateShow(boolean show, Runnable onDone, Runnable onPartly, boolean showback) { if (imageViewEmoji == null) { if (onDone != null) { @@ -5008,6 +5280,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private float showMenuT; private boolean showingMenu; private ValueAnimator showMenuAnimator; + private void animateMenuShow(boolean show, Runnable onDone) { if (showMenuAnimator != null) { if (showingMenu == show) { @@ -5074,11 +5347,12 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public void show() { super.show(); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 4); - animateShow(true, null, null,true); + animateShow(true, null, null, true); animateMenuShow(true, null); } private boolean dismissed = false; + @Override public void dismiss() { if (dismissed) { @@ -5098,7 +5372,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati @Override public void setPressed(boolean pressed) { - return; + return; } public void setAnimationsEnabled(boolean aniationsEnabled) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java index 6cabab498..d19adbcb0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java @@ -38,22 +38,20 @@ public class SponsoredMessageInfoView extends FrameLayout { textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); LinkSpanDrawable.LinksTextView description1 = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); - description1.setText(AndroidUtilities.replaceSingleTag(LocaleController.getString("SponsoredMessageInfoDescriptionLink", R.string.SponsoredMessageInfoDescriptionLink), () -> { - Browser.openUrl(getContext(), "https://telegram.org/privacy#5-6-no-ads-based-on-user-data"); - })); + description1.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description1"), resourcesProvider)); description1.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); description1.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); description1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); description1.setLineSpacing(AndroidUtilities.dp(2), 1f); - TextView description2 = new TextView(context); - description2.setText(LocaleController.getString("SponsoredMessageInfoDescription2", R.string.SponsoredMessageInfoDescription2)); + LinkSpanDrawable.LinksTextView description2 = new LinkSpanDrawable.LinksTextView(context); + description2.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description2"), resourcesProvider)); description2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); description2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); description2.setLineSpacing(AndroidUtilities.dp(2), 1f); - TextView description3 = new TextView(context); - description3.setText(LocaleController.getString("SponsoredMessageInfoDescription3", R.string.SponsoredMessageInfoDescription3)); + LinkSpanDrawable.LinksTextView description3 = new LinkSpanDrawable.LinksTextView(context); + description3.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description3"), resourcesProvider)); description3.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); description3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); description3.setLineSpacing(AndroidUtilities.dp(2), 1f); @@ -86,22 +84,32 @@ public class SponsoredMessageInfoView extends FrameLayout { button.setGravity(Gravity.CENTER_VERTICAL); - TextView description4 = new TextView(context); - description4.setText(LocaleController.getString("SponsoredMessageInfoDescription4", R.string.SponsoredMessageInfoDescription4)); + LinkSpanDrawable.LinksTextView description4 = new LinkSpanDrawable.LinksTextView(context); + description4.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description4"), resourcesProvider)); description4.setLineSpacing(AndroidUtilities.dp(2), 1f); description4.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); description4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); linearLayout.addView(textView); + + description1.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); linearLayout.addView(description1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 18, 0, 0)); + + description2.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); linearLayout.addView(description2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 24, 0, 0)); + + description3.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); linearLayout.addView(description3, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 24, 0, 0)); - linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 0, 14, 0, 0)); + + linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 22, 14, 22, 0)); + + description4.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); linearLayout.addView(description4, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 14, 0, 0)); ScrollView scrollView = new ScrollView(getContext()); scrollView.addView(linearLayout); - addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 22, 12, 22, 22)); + addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 12, 0, 22)); } } 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 7438caa7c..9afa2d84f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -1594,13 +1594,15 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter .setBgColor(Theme.getColor(Theme.key_undo_background)) .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_CENTER) - .setText(AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint"), Theme.key_undo_cancelColor, 0, () -> { - if (premiumHint != null) { - premiumHint.hide(); - } - fragment.presentFragment(new PremiumPreviewFragment("stories")); - })) .setJoint(0, 37 - 8); + CharSequence text = AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint").replace('\n', ' '), Theme.key_undo_cancelColor, 0, () -> { + if (premiumHint != null) { + premiumHint.hide(); + } + fragment.presentFragment(new PremiumPreviewFragment("stories")); + }); + premiumHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, premiumHint.getTextPaint())); + premiumHint.setText(text); premiumHint.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(24), AndroidUtilities.dp(8), 0); if (getParent() instanceof FrameLayout) { ((FrameLayout) getParent()).addView(premiumHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 150, Gravity.LEFT | Gravity.TOP)); @@ -1614,7 +1616,6 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter if (premiumHint.shown()) { BotWebViewVibrationEffect.APP_ERROR.vibrate(); } - premiumHint.setMaxWidthPx(Math.min(AndroidUtilities.dp(450), (int) (AndroidUtilities.displaySize.x * .7f))); premiumHint.show(); } } 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 4043fd9b6..2168f3c24 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -39,7 +39,6 @@ import android.view.SurfaceView; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; -import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -59,7 +58,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; @@ -96,7 +94,6 @@ 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.ChatMessageCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; @@ -132,12 +129,11 @@ import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.URLSpanMono; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.URLSpanReplacement; import org.telegram.ui.Components.URLSpanUserMention; -import org.telegram.ui.Components.spoilers.SpoilersTextView; import org.telegram.ui.Components.voip.CellFlickerDrawable; -import org.telegram.ui.DialogsActivity; import org.telegram.ui.LaunchActivity; import org.telegram.ui.NotificationsCustomSettingsActivity; import org.telegram.ui.PinchToZoomHelper; @@ -174,7 +170,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica // private final CloseFriendsBadge closeFriendsBadge; private final StoryPrivacyButton privacyButton; private HintView2 privacyHint; - private HintView soundTooltip; + private HintView2 soundTooltip; private int reactionsContainerIndex; private final StoryViewer storyViewer; private final StoryCaptionView storyCaptionView; @@ -271,8 +267,6 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica public boolean allowScreenshots; public boolean forceUpdateOffsets; private HintView mediaBanTooltip; -// private HintView closeFriendsTooltip; - ArrayList createdTooltips = new ArrayList<>(); public PinchToZoomHelper pinchToZoomHelper = new PinchToZoomHelper(); private boolean imageChanged; @@ -308,6 +302,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica this.uploadingStories = new ArrayList<>(); this.imageReceiver = new ImageReceiver() { + @Override protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) { boolean r = super.setImageBitmapByKey(drawable, key, type, memCache, guid); @@ -332,6 +327,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica this.rightPreloadImageReceiver.setAllowLoadingOnAttachedOnly(true); this.rightPreloadImageReceiver.ignoreNotifications = true; this.rightPreloadImageReceiver.setFileLoadingPriority(FileLoader.PRIORITY_LOW); + imageReceiver.setPreloadingReceivers(Arrays.asList(leftPreloadImageReceiver, rightPreloadImageReceiver)); this.avatarDrawable = new AvatarDrawable(); this.storyViewer = storyViewer; @@ -656,7 +652,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica storyCaptionView = new StoryCaptionView(getContext(), storyViewer.resourcesProvider) { @Override - public void onLinkClick(ClickableSpan span, View spoilersTextView) { + public void onLinkClick(CharacterStyle span, View spoilersTextView) { if (span instanceof URLSpanUserMention) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(Utilities.parseLong(((URLSpanUserMention) span).getURL())); if (user != null) { @@ -678,8 +674,11 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } else if (span instanceof URLSpan) { String url = ((URLSpan) span).getURL(); processExternalUrl(2, url, span, span instanceof URLSpanReplacement); - } else { - span.onClick(spoilersTextView); + } else if (span instanceof URLSpanMono) { + ((URLSpanMono) span).copyToClipboard(); + BulletinFactory.of(storyContainer, resourcesProvider).createCopyBulletin(LocaleController.getString("TextCopied", R.string.TextCopied)).show(); + } else if (span instanceof ClickableSpan) { + ((ClickableSpan) span).onClick(spoilersTextView); } } @@ -959,7 +958,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica }); } - if (allowShare) { + if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_shareout, LocaleController.getString("BotShare", R.string.BotShare), false, resourcesProvider).setOnClickListener(v -> { shareStory(false); if (popupMenu != null) { @@ -1024,7 +1023,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } if (user.contact) { if (!user.stories_hidden) { - ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_archive, LocaleController.getString("ArchiveStories", R.string.ArchiveStories), false, resourcesProvider).setOnClickListener(v -> { + ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), false, resourcesProvider).setOnClickListener(v -> { toggleArciveForStory(dialogId); if (popupMenu != null) { popupMenu.dismiss(); @@ -1042,16 +1041,16 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } if (!unsupported) { - //if (UserObject.isService(dialogId)) { + if (UserObject.isService(dialogId) || allowShare) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), false, resourcesProvider).setOnClickListener(v -> { saveToGallery(); if (popupMenu != null) { popupMenu.dismiss(); } }); - // } + } } - if (allowShare) { + if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { AndroidUtilities.addToClipboard(currentStory.createLink()); onLickCopied(); @@ -1163,16 +1162,18 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica firstName = firstName.substring(0, index); } CharSequence text; + boolean twoLines = true; if (storyItem.close_friends) { text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryCloseFriendsHint", R.string.StoryCloseFriendsHint, firstName)); } else if (storyItem.contacts) { text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryContactsHint", R.string.StoryContactsHint, firstName)); + twoLines = false; } else if (storyItem.selected_contacts) { text = AndroidUtilities.replaceTags(LocaleController.formatString("StorySelectedContactsHint", R.string.StorySelectedContactsHint, firstName)); } else { return; } - privacyHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, privacyHint.getTextPaint())); + privacyHint.setMaxWidthPx(twoLines ? HintView2.cutInFancyHalf(text, privacyHint.getTextPaint()) : storyContainer.getMeasuredWidth()); privacyHint.setText(text); privacyHint.setJoint(1, -(storyContainer.getWidth() - privacyButton.getCenterX()) / AndroidUtilities.density); delegate.setIsHintVisible(true); @@ -1189,16 +1190,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica storyViewer.toggleSilentMode(); } else { if (soundTooltip == null) { - soundTooltip = new HintView.Builder(context, resourcesProvider) - .setTopArrow(true) - .setBackgroundColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (0.5f * 255))) - .build(); - soundTooltip.setExtraTranslationY(-dp(8)); + soundTooltip = new HintView2(context, HintView2.DIRECTION_TOP).setJoint(1, -56); soundTooltip.setText(LocaleController.getString(R.string.StoryNoSound)); - addView(soundTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); - createdTooltips.add(soundTooltip); + soundTooltip.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + storyContainer.addView(soundTooltip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.TOP, 0, 52, 0, 0)); } - soundTooltip.showForView(muteIconContainer, true); + soundTooltip.show(); } }); @@ -1906,6 +1903,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica this.dialogId = dialogId; deletedPeer = false; forceUpdateOffsets = true; + if (peerIdChanged) { + currentStory.clear(); + } if (dialogId >= 0) { isSelf = dialogId == UserConfig.getInstance(currentAccount).getClientUserId(); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); @@ -2274,7 +2274,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.storiesUpdated) { + if (id == NotificationCenter.storiesUpdated || id == NotificationCenter.storiesListUpdated && storyViewer.storiesList == args[0]) { if (delegate != null && delegate.isClosed()) { return; } @@ -2327,15 +2327,14 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica final boolean wasUploading = isUploading; final boolean wasEditing = isEditing; - if (isActive) { - ImageLoader.getInstance().cancelLoadingForImageReceiver(leftPreloadImageReceiver, true); - ImageLoader.getInstance().cancelLoadingForImageReceiver(rightPreloadImageReceiver, true); - } currentStory.editingSourceItem = null; if (!uploadingStories.isEmpty() && position >= storyItems.size()) { isUploading = true; isEditing = false; position -= storyItems.size(); + if (position < 0 || position >= uploadingStories.size()) { + return; + } StoriesController.UploadingStory uploadingStory = uploadingStories.get(position); Drawable thumbDrawable = null; imageReceiver.setCrossfadeWithOldImage(false); @@ -2355,6 +2354,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } else { isUploading = false; isEditing = false; + if (position < 0 || position > storyItems.size() - 1) { + storyViewer.close(true); + } TLRPC.StoryItem storyItem = storyItems.get(position); StoriesController.UploadingStory editingStory = storiesController.findEditingStory(storyItem); if (editingStory != null) { @@ -2385,7 +2387,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (storyItem.media != null) { thumbDrawable = ImageLoader.createStripedBitmap(storyItem.media.document.thumbs); } - if (ImageLoader.getInstance().isInMemCache(ImageLocation.getForPath(storyItem.firstFramePath).getKey(null, null, false) + "@" + filter, false)) { + if (storyItem.firstFramePath != null && ImageLoader.getInstance().isInMemCache(ImageLocation.getForPath(storyItem.firstFramePath).getKey(null, null, false) + "@" + filter, false)) { imageReceiver.setImage(null, null, ImageLocation.getForPath(storyItem.firstFramePath), filter, null, null, thumbDrawable, 0, null, null, 0); } else { imageReceiver.setImage(null, null, ImageLocation.getForPath(storyItem.attachPath), filter + "_pframe", null, null, thumbDrawable, 0, null, null, 0); @@ -2436,7 +2438,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica allowShare = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TLRPC.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped); if (allowShare) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); - allowShare = !currentStory.storyItem.noforwards && (currentStory.storyItem.isPublic || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) && user != null && UserObject.getPublicUsername(user) != null; + allowShare = !currentStory.storyItem.noforwards && currentStory.storyItem.isPublic && user != null && UserObject.getPublicUsername(user) != null; } NotificationsController.getInstance(currentAccount).processReadStories(dialogId, storyItem.id); } @@ -2501,12 +2503,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica headerView.setSubtitle(string, animateSubtitle); } } - for (int i = 0; i < createdTooltips.size(); i++) { - createdTooltips.get(i).hide(false); - } if (privacyHint != null) { privacyHint.hide(false); } + if (soundTooltip != null) { + soundTooltip.hide(false); + } } CharSequence caption = null; if (currentStory.uploadingStory != null) { @@ -2579,9 +2581,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (isActive) { + requestVideoPlayer(0); updatePreloadImages(); imageReceiver.bumpPriority(); - requestVideoPlayer(0); } if (storyViewer.storiesList != null && selectedPosition >= 0 && selectedPosition < storyViewer.storiesList.messageObjects.size()) { @@ -2987,11 +2989,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (privacyHint != null) { privacyHint.hide(); } - for (int i = 0; i < createdTooltips.size(); i++) { - if (createdTooltips.get(i).getVisibility() == View.VISIBLE) { - createdTooltips.get(i).hide(true); - return true; - } + if (soundTooltip != null) { + soundTooltip.hide(); } if (mediaBanTooltip != null) { @@ -3033,10 +3032,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (privacyHint != null && privacyHint.shown()) { return true; } - for (int i = 0; i < createdTooltips.size(); i++) { - if (createdTooltips.get(i).getVisibility() == View.VISIBLE) { - return true; - } + if (soundTooltip != null && soundTooltip.shown()) { + return true; } for (int i = 0; i < container.getChildCount(); i++) { @@ -3263,22 +3260,25 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public void onActionDown(MotionEvent ev) { - for (int i = 0; i < createdTooltips.size(); i++) { - createdTooltips.get(i).hide(); - } if (privacyHint != null && privacyHint.shown() && privacyButton != null && !privacyHint.containsTouch(ev, getX() + storyContainer.getX() + privacyHint.getX(), getY() + storyContainer.getY() + privacyHint.getY()) && - !hitPrivacyButton(ev) + !hitButton(privacyButton, ev) ) { privacyHint.hide(); } + if (soundTooltip != null && soundTooltip.shown() && muteIconContainer != null && + !soundTooltip.containsTouch(ev, getX() + storyContainer.getX() + soundTooltip.getX(), getY() + storyContainer.getY() + soundTooltip.getY()) && + !hitButton(muteIconContainer, ev) + ) { + soundTooltip.hide(); + } } - private boolean hitPrivacyButton(MotionEvent e) { - float ox = getX() + storyContainer.getX() + privacyButton.getX(), oy = getY() + storyContainer.getY() + privacyButton.getY(); + private boolean hitButton(View v, MotionEvent e) { + float ox = getX() + storyContainer.getX() + v.getX(), oy = getY() + storyContainer.getY() + v.getY(); return ( - e.getX() >= ox && e.getX() <= ox + privacyButton.getWidth() && - e.getY() >= oy && e.getY() <= oy + privacyButton.getHeight() + e.getX() >= ox && e.getX() <= ox + v.getWidth() && + e.getY() >= oy && e.getY() <= oy + v.getHeight() ); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java index 337933f1e..d9a266178 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java @@ -165,8 +165,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif final TLRPC.TL_userStories userStories; if (userId == 0) { userStories = null; - } else if (stateStories != null) { - userStories = stateStories; +// } else if (stateStories != null) { +// userStories = stateStories; } else { userStories = userFullStories; } 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 3a5d5ca72..bc59e1192 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -210,13 +210,15 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente if (id == NotificationCenter.storiesUpdated) { if (storyItem.uploadingStory != null) { TLRPC.TL_userStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId); - for (int i = 0; i < stories.stories.size(); i++) { - TLRPC.StoryItem storyItem = stories.stories.get(i); - if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) { - this.storyItem.uploadingStory = null; - this.storyItem.storyItem = storyItem; - setStoryItem(this.storyItem); - break; + if (stories != null) { + for (int i = 0; i < stories.stories.size(); i++) { + TLRPC.StoryItem storyItem = stories.stories.get(i); + if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) { + this.storyItem.uploadingStory = null; + this.storyItem.storyItem = storyItem; + setStoryItem(this.storyItem); + break; + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java index 3438dadfc..a65624a18 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -10,7 +10,6 @@ import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import com.google.android.exoplayer2.util.Consumer; -import com.google.android.exoplayer2.util.Log; import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; @@ -157,13 +156,18 @@ public class StoriesController { } private void sortDialogStories(ArrayList list) { - fixDeletedStories(list); + fixDeletedAndNonContactsStories(list); Collections.sort(list, userStoriesComparator); } - private void fixDeletedStories(ArrayList list) { + private void fixDeletedAndNonContactsStories(ArrayList list) { for (int k = 0; k < list.size(); k++) { TLRPC.TL_userStories userStories = list.get(k); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userStories.user_id); + if (user != null && !user.contact) { + list.remove(k); + k--; + } for (int i = 0; i < userStories.stories.size(); i++) { if (userStories.stories.get(i) instanceof TLRPC.TL_storyItemDeleted) { userStories.stories.remove(i); @@ -578,6 +582,7 @@ public class StoriesController { AndroidUtilities.runOnUIThread(() -> { TLRPC.TL_userStories currentUserStory = allStoriesMap.get(updateStory.user_id); FileLog.d("StoriesController update stories for user " + updateStory.user_id); + updateStoriesInLists(updateStory.user_id, Collections.singletonList(updateStory.story)); ArrayList newStoryItems = new ArrayList<>(); int oldStoriesCount = totalStoriesCount; @@ -645,7 +650,6 @@ public class StoriesController { } notify = true; } - updateStoriesInLists(updateStory.user_id, newStoryItems); } else { if (updateStory.story instanceof TLRPC.TL_storyItemDeleted) { FileLog.d("StoriesController can't add user " + updateStory.user_id + " with new story DELETED"); @@ -671,8 +675,8 @@ public class StoriesController { if (oldStoriesCount != totalStoriesCount) { mainSettings.edit().putInt("total_stores", totalStoriesCount).apply(); } - fixDeletedStories(dialogListStories); - fixDeletedStories(hiddenListStories); + fixDeletedAndNonContactsStories(dialogListStories); + fixDeletedAndNonContactsStories(hiddenListStories); if (notify) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); } @@ -789,14 +793,13 @@ public class StoriesController { req.id.add(storyItem.id); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { - AndroidUtilities.runOnUIThread(() -> { - updateDeletedStoriesInLists(getSelfUserId(), Arrays.asList(storyItem)); - }); + } }); storiesStorage.deleteStory(getSelfUserId(), storyItem.id); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); MessagesController.getInstance(currentAccount).checkArchiveFolder(); + updateDeletedStoriesInLists(getSelfUserId(), Arrays.asList(storyItem)); } public void deleteStories(ArrayList storyItems) { @@ -2126,6 +2129,9 @@ public class StoriesController { } boolean contains = loadedObjects.contains(storyItem.id) || cachedObjects.contains(storyItem.id); boolean shouldContain = type == TYPE_ARCHIVE ? true : storyItem.pinned; + if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + shouldContain = false; + } if (contains != shouldContain) { changed = true; if (!shouldContain) { @@ -2249,4 +2255,9 @@ public class StoriesController { public boolean hasOnlySelfStories() { return hasSelfStories() && (getDialogListStories().isEmpty() || (getDialogListStories().size() == 1 && getDialogListStories().get(0).user_id == UserConfig.getInstance(currentAccount).clientUserId)); } + + public void sortHiddenStories() { + sortDialogStories(hiddenListStories); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); + } } 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 705c61a91..59924c88e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -3,9 +3,10 @@ package org.telegram.ui.Stories; import android.graphics.Canvas; import android.view.View; -import androidx.recyclerview.widget.RecyclerView; - import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatMessageCell; @@ -20,12 +21,18 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { private final RecyclerListView recyclerListView; int[] clipPoint = new int[2]; + private boolean isHiddenArchive; public static StoriesListPlaceProvider of(RecyclerListView recyclerListView) { - return new StoriesListPlaceProvider(recyclerListView); + return of(recyclerListView, false); } - public StoriesListPlaceProvider(RecyclerListView recyclerListView) { + + public static StoriesListPlaceProvider of(RecyclerListView recyclerListView, boolean hiddenArchive) { + return new StoriesListPlaceProvider(recyclerListView, hiddenArchive); + } + public StoriesListPlaceProvider(RecyclerListView recyclerListView, boolean hiddenArchive) { this.recyclerListView = recyclerListView; + this.isHiddenArchive = hiddenArchive; } @Override @@ -38,6 +45,9 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { r.run(); } } else { + if (isHiddenArchive) { + MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().sortHiddenStories(); + } r.run(); } } @@ -48,6 +58,10 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { holder.storyImage = null; holder.drawAbove = null; + if (recyclerListView == null) { + return false; + } + DialogStoriesCell dialogStoriesCell = null; if (recyclerListView.getParent() instanceof DialogStoriesCell) { dialogStoriesCell = (DialogStoriesCell) recyclerListView.getParent(); @@ -75,11 +89,14 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { } } else if (child instanceof DialogCell) { DialogCell cell = (DialogCell) child; - if (cell.getDialogId() == dialogId) { + if (cell.getDialogId() == dialogId || (isHiddenArchive && cell.isDialogFolder())) { holder.view = child; - holder.params = cell.params; + holder.params = cell.storyParams; holder.avatarImage = cell.avatarImage; holder.clipParent = (View) cell.getParent(); + if (isHiddenArchive) { + holder.crossfadeToAvatarImage = cell.avatarImage; + } updateClip(holder); return true; } 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 45b88c094..7d8535daf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java @@ -13,6 +13,8 @@ import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; import android.widget.TextView; import androidx.core.graphics.ColorUtils; @@ -102,6 +104,10 @@ public class StoriesUtilities { int unreadState = 0; boolean showProgress = storiesController.isLoading(dialogId); + if (params.drawHiddenStoriesAsSegments) { + hasStories = storiesController.hasHiddenStories(); + } + if (params.storyItem != null) { unreadState = storiesController.getUnreadState(dialogId, params.storyId); state = unreadState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD; @@ -247,7 +253,13 @@ public class StoriesUtilities { int globalState = storiesController.getUnreadState(dialogId); params.globalState = globalState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD; TLRPC.TL_userStories userStories = storiesController.getStories(params.dialogId); - if (userStories == null || userStories.stories.size() == 1) { + int storiesCount; + if (params.drawHiddenStoriesAsSegments) { + storiesCount = storiesController.getHiddenList().size(); + } else { + storiesCount = userStories == null || userStories.stories.size() == 1 ? 1 : userStories.stories.size(); + } + if (storiesCount == 1) { Paint localPaint = paint; if (storiesController.hasUnreadStories(dialogId)) { localPaint = unreadPaint; @@ -259,9 +271,9 @@ public class StoriesUtilities { endAngle = 270; drawSegment(canvas, rectTmp, localPaint, startAngle, endAngle, params); // canvas.drawCircle(rectTmp.centerX(), rectTmp.centerY(), rectTmp.width() / 2f, localPaint); - } else if (userStories != null) { - float step = 360 / (float) userStories.stories.size(); - int gap = userStories.stories.size() > 20 ? 3 : 5; + } else { + float step = 360 / (float) storiesCount; + int gap = storiesCount > 20 ? 3 : 5; float gapLen = gap * params.progressToSegments; if (gapLen > step) { gapLen = 0;//step * 0.4f; @@ -277,15 +289,24 @@ public class StoriesUtilities { globalPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint; } - int maxUnread = Math.max(userStories.max_read_id, storiesController.dialogIdToMaxReadId.get(dialogId, 0)); - for (int i = 0; i < userStories.stories.size(); i++) { + int maxUnread = params.drawHiddenStoriesAsSegments ? 0 : Math.max(userStories.max_read_id, storiesController.dialogIdToMaxReadId.get(dialogId, 0)); + for (int i = 0; i < storiesCount; i++) { Paint segmentPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint; - if (userStories.stories.get(i).justUploaded || userStories.stories.get(i).id > maxUnread) { - if (userStories.stories.get(i).close_friends) { + if (params.drawHiddenStoriesAsSegments) { + int userUnreadState = storiesController.getUnreadState(storiesController.getHiddenList().get(storiesCount - 1 - i).user_id); + if (userUnreadState == StoriesController.STATE_UNREAD_CLOSE_FRIEND) { segmentPaint = closeFriendsPaint; - } else { + } else if (userUnreadState == StoriesController.STATE_UNREAD) { segmentPaint = unreadPaint; } + } else { + if (userStories.stories.get(i).justUploaded || userStories.stories.get(i).id > maxUnread) { + if (userStories.stories.get(i).close_friends) { + segmentPaint = closeFriendsPaint; + } else { + segmentPaint = unreadPaint; + } + } } float startAngle = step * i - 90; float endAngle = startAngle + step; @@ -541,6 +562,9 @@ public class StoriesUtilities { } public static void setImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem, String filter) { + if (storyItem == null) { + return; + } if (storyItem.media != null && storyItem.media.document != null) { TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(storyItem.media.document.thumbs, Integer.MAX_VALUE); imageReceiver.setImage(ImageLocation.getForDocument(size, storyItem.media.document), filter, null, null, ImageLoader.createStripedBitmap(storyItem.media.document.thumbs), 0, null, storyItem, 0); @@ -683,6 +707,9 @@ public class StoriesUtilities { } public static void applyViewedUser(TLRPC.StoryItem storyItem, TLRPC.User currentUser) { + if (currentUser == null) { + return; + } if (storyItem.dialogId == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && !hasExpiredViews(storyItem)) { if (storyItem.views == null) { storyItem.views = new TLRPC.TL_storyViews(); @@ -743,6 +770,7 @@ public class StoriesUtilities { public int prevUnreadState; public int unreadState; public int animateFromUnreadState; + public boolean drawHiddenStoriesAsSegments; private long dialogId; public int currentState; @@ -795,9 +823,16 @@ public class StoriesUtilities { Runnable longPressRunnable; public boolean checkOnTouchEvent(MotionEvent event, View 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); - if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && (MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasStories(dialogId) || user != null && !user.stories_unavailable && user.stories_max_id > 0)) { + boolean hasStories; + if (drawHiddenStoriesAsSegments) { + hasStories = storiesController.hasHiddenStories(); + } else { + hasStories = (MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasStories(dialogId) || user != null && !user.stories_unavailable && user.stories_max_id > 0); + } + if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && hasStories) { if (buttonBounce == null) { buttonBounce = new ButtonBounce(view, 1.5f); } else { @@ -817,7 +852,10 @@ public class StoriesUtilities { if (buttonBounce != null) { buttonBounce.setPressed(false); } - view.getParent().requestDisallowInterceptTouchEvent(false); + ViewParent parent = view.getParent(); + if (parent instanceof ViewGroup) { + ((ViewGroup) parent).requestDisallowInterceptTouchEvent(false); + } pressed = false; onLongPress(); }, ViewConfiguration.getLongPressTimeout()); @@ -843,7 +881,10 @@ public class StoriesUtilities { if (pressed && event.getAction() == MotionEvent.ACTION_UP) { processOpenStory(view); } - view.getParent().requestDisallowInterceptTouchEvent(false); + ViewParent parent = view.getParent(); + if (parent instanceof ViewGroup) { + ((ViewGroup) parent).requestDisallowInterceptTouchEvent(false); + } pressed = false; if (longPressRunnable != null) { AndroidUtilities.cancelRunOnUIThread(longPressRunnable); @@ -860,6 +901,10 @@ public class StoriesUtilities { int currentAccount = UserConfig.selectedAccount; MessagesController messagesController = MessagesController.getInstance(UserConfig.selectedAccount); StoriesController storiesController = messagesController.getStoriesController(); + if (drawHiddenStoriesAsSegments) { + openStory(0, null); + return; + } if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId()) { if (storiesController.hasStories(dialogId)) { openStory(dialogId, null); 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 ef4924708..fb6dcc79d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java @@ -82,6 +82,7 @@ public class StoriesViewPager extends ViewPager { pageLayout.peerStoryView = view; view.setAccount(currentAccount); view.setDelegate(delegate); + view.setLongpressed(storyViewer.isLongpressed); pageLayout.setTag(position); pageLayout.dialogId = dialogs.get(position); pageLayout.addView(view); 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 8fa631836..3fd7df309 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java @@ -21,6 +21,7 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.view.MotionEvent; @@ -55,6 +56,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.LinkSpanDrawable; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.URLSpanMono; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.spoilers.SpoilersClickDetector; import org.telegram.ui.Components.spoilers.SpoilersTextView; @@ -151,7 +153,7 @@ public class StoryCaptionView extends NestedScrollView { } - public void onLinkClick(ClickableSpan span, View spoilersTextView) { + public void onLinkClick(CharacterStyle span, View spoilersTextView) { } @@ -540,7 +542,7 @@ public class StoryCaptionView extends NestedScrollView { public class StoryCaptionTextView extends View { private final PorterDuffColorFilter emojiColorFilter; - private LinkSpanDrawable pressedLink; + private LinkSpanDrawable pressedLink; private AnimatedEmojiSpan pressedEmoji; private LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this); @@ -783,7 +785,7 @@ public class StoryCaptionView extends NestedScrollView { if (Build.VERSION.SDK_INT >= 24) { return StaticLayout.Builder.obtain(string, 0, string.length(), textPaint, width).setBreakStrategy(StaticLayout.BREAK_STRATEGY_SIMPLE).setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE).setAlignment(LocaleController.isRTL ? StaticLayoutEx.ALIGN_RIGHT() : StaticLayoutEx.ALIGN_LEFT()).build(); } else { - return new StaticLayout(string, Theme.profile_aboutTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + return new StaticLayout(string, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } } @@ -818,11 +820,14 @@ public class StoryCaptionView extends NestedScrollView { final int off = fullLayout.getOffsetForHorizontal(line, x); final float left = fullLayout.getLineLeft(line); - ClickableSpan touchLink = null; + CharacterStyle touchLink = null; AnimatedEmojiSpan touchEmoji = null; if (left <= x && left + fullLayout.getLineWidth(line) >= x && y >= 0 && y <= fullLayout.getHeight()) { Spannable buffer = new SpannableString(text); - ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); + CharacterStyle[] link = buffer.getSpans(off, off, ClickableSpan.class); + if (link == null || link.length == 0) { + link = buffer.getSpans(off, off, URLSpanMono.class); + } if (link != null && link.length != 0) { touchLink = link[0]; if (event.getAction() == MotionEvent.ACTION_DOWN) { @@ -838,7 +843,7 @@ public class StoryCaptionView extends NestedScrollView { path.setCurrentLayout(fullLayout, start, getPaddingTop()); fullLayout.getSelectionPath(start, end, path); - final LinkSpanDrawable savedPressedLink = pressedLink; + final LinkSpanDrawable savedPressedLink = pressedLink; postDelayed(() -> { if (savedPressedLink == pressedLink && pressedLink != null && pressedLink.getSpan() instanceof URLSpan) { onLinkLongPress((URLSpan) pressedLink.getSpan(), this, () -> links.clear()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryContainsEmojiButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryContainsEmojiButton.java index 544a263fc..8ada537bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryContainsEmojiButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryContainsEmojiButton.java @@ -125,15 +125,16 @@ public class StoryContainsEmojiButton extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final boolean exactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; + + final int height = getPaddingTop() + AndroidUtilities.lerp(dp(29), layout == null ? dp(29) : layout.getHeight(), loadT) + getPaddingBottom(); + setMeasuredDimension(exactly ? MeasureSpec.getSize(widthMeasureSpec) : getMinimumWidth(), height); + final int contentWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); if (exactly && (toSetText != null || layout != null && lastContentWidth != contentWidth)) { setText(toSetText != null ? toSetText : layout.getText()); toSetText = null; lastContentWidth = contentWidth; } - - final int height = getPaddingTop() + AndroidUtilities.lerp(dp(29), layout == null ? dp(29) : layout.getHeight(), loadT) + getPaddingBottom(); - setMeasuredDimension(exactly ? MeasureSpec.getSize(widthMeasureSpec) : getMinimumWidth(), height); } @Override @@ -207,6 +208,9 @@ public class StoryContainsEmojiButton extends View { req.media = inputStickeredMediaDocument; } final RequestDelegate requestDelegate = (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response == null) { + return; + } TLRPC.Vector vector = this.vector = (TLRPC.Vector) response; lastRequestParentObject = parentObject; lastResponse = vector; 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 8594b1307..7ba5538dc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -118,6 +118,7 @@ public class StoryViewer { float fromWidth; float fromHeight; + RectF avatarRectTmp = new RectF(); float progressToOpen; float progressToDismiss; float swipeToDismissOffset; @@ -185,7 +186,7 @@ public class StoryViewer { private static boolean runOpenAnimationAfterLayout; private boolean isPopupVisible; - private boolean isLongpressed; + public boolean isLongpressed; Runnable longPressRunnable = () -> setLongPressed(true); @@ -225,7 +226,12 @@ public class StoryViewer { if (isLongpressed != b) { isLongpressed = b; updatePlayingMode(); - storiesViewPager.getCurrentPeerView().setLongpressed(isLongpressed); + if (storiesViewPager != null) { + PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.setLongpressed(isLongpressed); + } + } } } @@ -474,6 +480,15 @@ public class StoryViewer { final RectF outFromRectAvatar = new RectF(); final RectF outFromRectContainer = new RectF(); + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == aspectRatioFrameLayout) { + return false; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override protected void dispatchDraw(Canvas canvas) { float blackoutAlpha = getBlackoutAlpha(); @@ -669,12 +684,36 @@ public class StoryViewer { AndroidUtilities.lerp(rect1, rect2, progressToOpen, AndroidUtilities.rectTmp); if (animateAvatar) { - headerView.backupImageView.getImageReceiver().setImageCoords(AndroidUtilities.rectTmp); - headerView.backupImageView.getImageReceiver().setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f)); - headerView.backupImageView.getImageReceiver().setVisible(true, false); - headerView.drawUploadingProgress(canvas, AndroidUtilities.rectTmp, !runOpenAnimationAfterLayout, progressToOpen); - headerView.backupImageView.getImageReceiver().draw(canvas); - headerView.backupImageView.getImageReceiver().setVisible(false, false); + boolean crossfade = transitionViewHolder != null && transitionViewHolder.crossfadeToAvatarImage != null; + if (!crossfade || progressToOpen != 0) { + headerView.backupImageView.getImageReceiver().setImageCoords(AndroidUtilities.rectTmp); + headerView.backupImageView.getImageReceiver().setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f)); + headerView.backupImageView.getImageReceiver().setVisible(true, false); + headerView.backupImageView.getImageReceiver().setAlpha(crossfade ? progressToOpen : 1f); + headerView.drawUploadingProgress(canvas, AndroidUtilities.rectTmp, !runOpenAnimationAfterLayout, progressToOpen); + headerView.backupImageView.getImageReceiver().draw(canvas); + headerView.backupImageView.getImageReceiver().setVisible(false, false); + } + if (progressToOpen != 1f && crossfade) { + avatarRectTmp.set( + transitionViewHolder.crossfadeToAvatarImage.getImageX(), + transitionViewHolder.crossfadeToAvatarImage.getImageY(), + transitionViewHolder.crossfadeToAvatarImage.getImageX2(), + transitionViewHolder.crossfadeToAvatarImage.getImageY2() + ); + int oldRadius = transitionViewHolder.crossfadeToAvatarImage.getRoundRadius()[0]; + boolean isVisible = transitionViewHolder.crossfadeToAvatarImage.getVisible(); + transitionViewHolder.crossfadeToAvatarImage.setImageCoords(AndroidUtilities.rectTmp); + transitionViewHolder.crossfadeToAvatarImage.setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f)); + transitionViewHolder.crossfadeToAvatarImage.setVisible(true, false); + canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * (1f - progressToOpen)), Canvas.ALL_SAVE_FLAG); + transitionViewHolder.crossfadeToAvatarImage.draw(canvas); + canvas.restore(); + transitionViewHolder.crossfadeToAvatarImage.setVisible(isVisible, false); + transitionViewHolder.crossfadeToAvatarImage.setImageCoords(avatarRectTmp); + transitionViewHolder.crossfadeToAvatarImage.setRoundRadius(oldRadius); + // transitionViewHolder.crossfadeToAvatarImage.setVisible(false, false); + } } } @@ -759,7 +798,7 @@ public class StoryViewer { boolean override = false; boolean enableTouch = !keyboardVisible && !isClosed && !isRecording; if (selfStoriesViewsOffset == 0 && !inSwipeToDissmissMode && storiesViewPager.currentState == ViewPager.SCROLL_STATE_DRAGGING && ev.getAction() == MotionEvent.ACTION_MOVE && enableTouch) { - float dx = lastX.get(ev.getPointerId(0)) - ev.getX(0); + float dx = lastX.get(ev.getPointerId(0), 0f) - ev.getX(0); if (dx != 0 && !storiesViewPager.canScroll(dx) || swipeToDismissHorizontalOffset != 0) { if (swipeToDismissHorizontalOffset == 0) { swipeToDismissHorizontalDirection = -dx; @@ -968,14 +1007,6 @@ public class StoryViewer { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child == aspectRatioFrameLayout) { - return true; - } - return super.drawChild(canvas, child, drawingTime); - } - @Override protected void dispatchDraw(Canvas canvas) { PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); @@ -1175,6 +1206,7 @@ public class StoryViewer { currentPlayerScope.textureView = textureView; currentPlayerScope.surfaceView = surfaceView; FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_HIGH); + FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_HIGH, playerHolder.document, null, null, null, null, null); currentPlayerScope.player.start(isPaused(), uri, t, isInSilentMode); currentPlayerScope.invalidate(); } @@ -1266,10 +1298,6 @@ public class StoryViewer { uries.remove(j); } } - if (!found) { - preparedPlayers.remove(i).release(null); - i--; - } } for (int i = 0; i < uries.size(); i++) { Uri uri = uries.get(i); @@ -1284,21 +1312,14 @@ public class StoryViewer { player.release(null); } } - } }); containerView.addView(storiesViewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL)); aspectRatioFrameLayout = new AspectRatioFrameLayout(context); if (USE_SURFACE_VIEW) { - surfaceView = new SurfaceView(context) { - @Override - public void invalidate() { - super.invalidate(); - if (currentPlayerScope != null) { - currentPlayerScope.invalidate(); - } - } - }; + surfaceView = new SurfaceView(context); + surfaceView.setZOrderMediaOverlay(false); + surfaceView.setZOrderOnTop(false); //surfaceView.setZOrderMediaOverlay(true); aspectRatioFrameLayout.addView(surfaceView); } else { @@ -1315,12 +1336,14 @@ public class StoryViewer { } - containerView.addView(aspectRatioFrameLayout); + volumeControl = new StoriesVolumeContorl(context); containerView.addView(volumeControl, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 4, 0, 4, 0)); } AndroidUtilities.removeFromParent(containerView); windowView.addView(containerView); + AndroidUtilities.removeFromParent(aspectRatioFrameLayout); + windowView.addView(aspectRatioFrameLayout); windowView.setClipChildren(false); if (ATTACH_TO_FRAGMENT) { @@ -1480,11 +1503,13 @@ public class StoryViewer { if (page == null || page.storyContainer == null) { return false; } + float x = windowView == null ? 0 : windowView.getX(); + float y = windowView == null ? 0 : windowView.getY(); rectF.set( - windowView.getX() + swipeToDismissHorizontalOffset + containerView.getLeft() + page.getX() + page.storyContainer.getX(), - windowView.getY() + swipeToDismissOffset + containerView.getTop() + page.getY() + page.storyContainer.getY(), - windowView.getX() + swipeToDismissHorizontalOffset + containerView.getRight() - (containerView.getWidth() - page.getRight()) - (page.getWidth() - page.storyContainer.getRight()), - windowView.getY() + swipeToDismissOffset + containerView.getBottom() - (containerView.getHeight() - page.getBottom()) - (page.getHeight() - page.storyContainer.getBottom()) + x + swipeToDismissHorizontalOffset + containerView.getLeft() + page.getX() + page.storyContainer.getX(), + y + swipeToDismissOffset + containerView.getTop() + page.getY() + page.storyContainer.getY(), + x + swipeToDismissHorizontalOffset + containerView.getRight() - (containerView.getWidth() - page.getRight()) - (page.getWidth() - page.storyContainer.getRight()), + y + swipeToDismissOffset + containerView.getBottom() - (containerView.getHeight() - page.getBottom()) - (page.getHeight() - page.storyContainer.getBottom()) ); return true; } @@ -1524,10 +1549,10 @@ public class StoryViewer { public void toggleSilentMode() { isInSilentMode = !isInSilentMode; if (playerHolder != null) { - playerHolder.setAudioEnabled(!isInSilentMode); + playerHolder.setAudioEnabled(!isInSilentMode, false); } for (int i = 0; i < preparedPlayers.size(); i++) { - preparedPlayers.get(i).setAudioEnabled(!isInSilentMode); + preparedPlayers.get(i).setAudioEnabled(!isInSilentMode, true); } PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); peerStoriesView.sharedResources.setIconMuted(!soundEnabled(), true); @@ -1758,7 +1783,10 @@ public class StoryViewer { if (progressToDismiss != newProgress) { progressToDismiss = newProgress; checkNavBarColor(); - storiesViewPager.getCurrentPeerView().progressToDismissUpdated(); + PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); + if (peerStoriesView != null) { + peerStoriesView.progressToDismissUpdated(); + } } if (windowView != null) { @@ -2137,10 +2165,12 @@ public class StoryViewer { surfaceView.setSecure(!allowScreenshots); } if (ATTACH_TO_FRAGMENT) { - if (allowScreenshots) { - fragment.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE); - } else { - fragment.getParentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); + if (fragment.getParentActivity() != null) { + if (allowScreenshots) { + fragment.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE); + } else { + fragment.getParentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); + } } } else { if (allowScreenshots) { @@ -2160,6 +2190,9 @@ public class StoryViewer { public void openFor(BaseFragment fragment, RecyclerListView recyclerListView, ChatActionCell cell) { MessageObject messageObject = cell.getMessageObject(); + if (fragment == null || fragment.getContext() == null) { + return; + } if (messageObject.type == MessageObject.TYPE_STORY_MENTION) { TLRPC.StoryItem storyItem = messageObject.messageOwner.media.storyItem; storyItem.dialogId = messageObject.messageOwner.media.user_id; @@ -2196,6 +2229,7 @@ public class StoryViewer { public View clipParent; public float clipTop; public float clipBottom; + public ImageReceiver crossfadeToAvatarImage; StoriesUtilities.AvatarStoryParams params; public void clear() { @@ -2207,6 +2241,7 @@ public class StoryViewer { drawClip = null; clipParent = null; radialProgressUpload = null; + crossfadeToAvatarImage = null; clipTop = 0; clipBottom = 0; } @@ -2474,7 +2509,7 @@ public class StoryViewer { }); } - public void setAudioEnabled(boolean enabled) { + public void setAudioEnabled(boolean enabled, boolean prepared) { boolean disabled = !enabled; if (audioDisabled == disabled) { return; @@ -2494,7 +2529,7 @@ public class StoryViewer { ensurePlayerCreated(audioDisabled); videoPlayer.preparePlayer(uri, "other"); videoPlayer.setWorkerQueue(dispatchQueue); - if (currentPlayerScope != null) { + if (!prepared) { if (USE_SURFACE_VIEW) { videoPlayer.setSurfaceView(surfaceView); } else { @@ -2503,7 +2538,7 @@ public class StoryViewer { } // videoPlayer.setTextureView(textureView); videoPlayer.seekTo(position + 50); - if (playing) { + if (playing && !prepared) { videoPlayer.setPlayWhenReady(true); videoPlayer.play(); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftSavedHint.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftSavedHint.java index ba674f77d..55b956923 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftSavedHint.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftSavedHint.java @@ -19,6 +19,7 @@ import androidx.annotation.NonNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CubicBezierInterpolator; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java index 48afbd328..4283b1486 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java @@ -482,13 +482,29 @@ public class DualCameraView extends CameraView implements CameraController.Error -862041025, // XIAOMI WILLOW -1258375037, // XIAOMI INGRES -1320049076, // XIAOMI GINKGO + -215749424, // XIAOMI LISA + 1901578030, // XIAOMI LEMON + -215451421, // XIAOMI VIVA + 1908491424, // XIAOMI STONE + -1321491332, // XIAOMI RAPHAEL + -1155551678, // XIAOMI MARBLE + 1908524435, // XIAOMI SURYA 976847578, // XIAOMI LAUREL_SPROUT -713271737, // OPPO OP4F2F -2010722764, // SAMSUNG A52SXQ (A52s 5G) 1407170066, // SAMSUNG D2Q (Note10+) -1394190055, // SAMSUNG B4Q 1407170066, // HUAWEI HWNAM + 1407159934, // HUAWEI HWCOR + 1407172057, // HUAWEI HWPCT 1231389747, // FAIRPHONE FP3 + -2076538925, // MOTOROLA RSTAR + 41497626, // MOTOROLA RHODEC + 846150482, // MOTOROLA CHANNEL + -1198092731, // MOTOROLA CYPRUS64 + -251277614, // MOTOROLA HANOIP + -2078385967, // MOTOROLA PSTAR +// -1426053134 // REALME REE2ADL1 }; private static final int[] dualWhitelistByModel = new int[] { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java index 0fb6839fd..02e432140 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java @@ -1917,7 +1917,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if (emojiLayout != null) { canvas.save(); - canvas.translate(emojiRect.left + dp(12) + emojiLayoutLeft, emojiRect.top + (emojiRect.height() - emojiLayout.getHeight()) / 2f); + canvas.translate(emojiRect.left + dp(12) - emojiLayoutLeft, emojiRect.top + (emojiRect.height() - emojiLayout.getHeight()) / 2f); textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 0), 1, 0))); emojiLayout.draw(canvas); canvas.restore(); @@ -1925,7 +1925,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if (stickersLayout != null) { canvas.save(); - canvas.translate(stickersRect.left + dp(12) + stickersLayoutLeft, stickersRect.top + (stickersRect.height() - stickersLayout.getHeight()) / 2f); + canvas.translate(stickersRect.left + dp(12) - stickersLayoutLeft, stickersRect.top + (stickersRect.height() - stickersLayout.getHeight()) / 2f); textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 1), 1, 0))); stickersLayout.draw(canvas); canvas.restore(); @@ -1933,7 +1933,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if (masksLayout != null) { canvas.save(); - canvas.translate(masksRect.left + dp(12) + masksLayoutLeft, masksRect.top + (masksRect.height() - masksLayout.getHeight()) / 2f); + canvas.translate(masksRect.left + dp(12) - masksLayoutLeft, masksRect.top + (masksRect.height() - masksLayout.getHeight()) / 2f); textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 2), 1, 0))); masksLayout.draw(canvas); canvas.restore(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java index 90cc246fe..728d86589 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java @@ -923,7 +923,7 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); setPadding(dp(16), dp(16), dp(21), dp(10)); - setText(LocaleController.getString(onlyPhotos ? R.string.ChoosePhoto : R.string.ChoosePhotoOrVideo)); + setText(LocaleController.getString(onlyPhotos ? R.string.AddImage : R.string.ChoosePhotoOrVideo)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java index 6915a31a3..540a7e70b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java @@ -26,6 +26,7 @@ public class HintTextView extends View { textDrawable.getPaint().setShadowLayer(AndroidUtilities.dp(1.4f), 0, AndroidUtilities.dp(.4f), 0x4C000000); textDrawable.setGravity(Gravity.CENTER_HORIZONTAL); textDrawable.setCallback(this); + textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); } public void setText(CharSequence text, boolean animated) { @@ -45,4 +46,10 @@ public class HintTextView extends View { protected boolean verifyDrawable(@NonNull Drawable who) { return who == textDrawable || super.verifyDrawable(who); } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + textDrawable.setOverrideFullWidth(getMeasuredWidth()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java index debbf22bc..9580f0d58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java @@ -86,6 +86,7 @@ public class HintView2 extends View { private float textX, textY; private boolean hideByTouch = true; + private boolean repeatedBounce = true; private boolean shown; private AnimatedFloat show = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); @@ -185,6 +186,18 @@ public class HintView2 extends View { return this; } + private static boolean contains(CharSequence text, char c) { + if (text == null) { + return false; + } + for (int i = 0; i < text.length(); ++i) { + if (text.charAt(i) == c) { + return true; + } + } + return false; + } + // returns max width public static int cutInFancyHalf(CharSequence text, TextPaint paint) { if (text == null) { @@ -257,6 +270,11 @@ public class HintView2 extends View { return this; } + public HintView2 setBounce(boolean enable) { + repeatedBounce = enable; + return this; + } + // works only for multiline=true public HintView2 setTextAlign(Layout.Alignment alignment) { textLayoutAlignment = alignment; @@ -318,6 +336,9 @@ public class HintView2 extends View { private ValueAnimator bounceAnimator; private float bounceT = 1; private void bounceShow() { + if (!repeatedBounce) { + return; + } if (bounceAnimator != null) { bounceAnimator.cancel(); bounceAnimator = null; @@ -487,7 +508,7 @@ public class HintView2 extends View { backgroundPaint.setAlpha(wasAlpha); if (multiline) { - canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); + canvas.saveLayerAlpha(0, 0, getWidth(), Math.max(getHeight(), height), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); canvas.translate(textX = bounds.left + innerPadding.left - textLayoutLeft, textY = bounds.top + innerPadding.top); if (links.draw(canvas)) { invalidate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java index 9f5279763..fb39c912f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java @@ -2739,8 +2739,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai deleteView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); deleteView.setBackground(Theme.getSelectorDrawable(false)); deleteView.setGravity(Gravity.CENTER_VERTICAL); + deleteView.setEllipsize(TextUtils.TruncateAt.END); deleteView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(14), 0); - deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); deleteView.setTag(0); deleteView.setText(LocaleController.getString("PaintDelete", R.string.PaintDelete)); deleteView.setOnClickListener(v -> { @@ -2757,8 +2758,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai editView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); editView.setBackground(Theme.getSelectorDrawable(false)); editView.setGravity(Gravity.CENTER_VERTICAL); + editView.setEllipsize(TextUtils.TruncateAt.END); editView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); - editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); if ((keyboardNotifier.keyboardVisible() && !keyboardNotifier.ignoring) || emojiPadding > 0) { editView.setTag(3); editView.setText(LocaleController.getString("Paste", R.string.Paste)); @@ -2791,9 +2793,10 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai TextView flipView = new TextView(getContext()); flipView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); flipView.setBackground(Theme.getSelectorDrawable(false)); + flipView.setEllipsize(TextUtils.TruncateAt.END); flipView.setGravity(Gravity.CENTER_VERTICAL); flipView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); - flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); flipView.setTag(4); flipView.setText(LocaleController.getString(R.string.Flip)); flipView.setOnClickListener(v -> { @@ -2809,22 +2812,25 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai parent.addView(flipView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48)); } - TextView duplicateView = new TextView(getContext()); - duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); - duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - duplicateView.setGravity(Gravity.CENTER_VERTICAL); - duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); - duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - duplicateView.setTag(2); - duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate)); - duplicateView.setOnClickListener(v -> { - duplicateEntity(entityView); + if (!(entityView instanceof PhotoView)) { + TextView duplicateView = new TextView(getContext()); + duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); + duplicateView.setBackground(Theme.getSelectorDrawable(false)); + duplicateView.setEllipsize(TextUtils.TruncateAt.END); + duplicateView.setGravity(Gravity.CENTER_VERTICAL); + duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + duplicateView.setTag(2); + duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate)); + duplicateView.setOnClickListener(v -> { + duplicateEntity(entityView); - if (popupWindow != null && popupWindow.isShowing()) { - popupWindow.dismiss(true); - } - }); - parent.addView(duplicateView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48)); + if (popupWindow != null && popupWindow.isShowing()) { + popupWindow.dismiss(true); + } + }); + parent.addView(duplicateView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48)); + } popupLayout.addView(parent); @@ -2855,6 +2861,8 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai newTextPaintView.setMaxWidth(w - AndroidUtilities.dp(7 + 7 + 18)); entitiesView.addView(newTextPaintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); entityView = newTextPaintView; + } else { + return; } registerRemovalUndo(entityView); @@ -3192,6 +3200,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai } private void registerRemovalUndo(final EntityView entityView) { + if (entityView == null) { + return; + } undoStore.registerUndo(entityView.getUUID(), () -> removeEntity(entityView)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java index ac08503fb..26a5227fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java @@ -278,6 +278,10 @@ public class PreviewView extends FrameLayout { } } } + if (imageId < 0 && entry.isVideo && entry.thumbPath == null) { + invalidate(); + return; + } if (bitmap == null) { String path = entry.getOriginalFile().getPath(); BitmapFactory.Options options = new BitmapFactory.Options(); @@ -286,7 +290,13 @@ public class PreviewView extends FrameLayout { if (entry.thumbPath != null) { BitmapFactory.decodeFile(entry.thumbPath, options); } else { - MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options); + try { + MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options); + } catch (Throwable e) { + bitmap = null; + invalidate(); + return; + } } } else { BitmapFactory.decodeFile(path, options); @@ -298,7 +308,13 @@ public class PreviewView extends FrameLayout { if (entry.thumbPath != null) { BitmapFactory.decodeFile(entry.thumbPath, options); } else { - bitmap = MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options); + try { + bitmap = MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options); + } catch (Throwable e) { + bitmap = null; + invalidate(); + return; + } } } else { bitmap = BitmapFactory.decodeFile(path, options); @@ -459,7 +475,9 @@ public class PreviewView extends FrameLayout { addView(textureView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT)); entry.detectHDR((hdrInfo) -> { - textureView.setHDRInfo(hdrInfo); + if (textureView != null) { + textureView.setHDRInfo(hdrInfo); + } }); Uri uri = Uri.fromFile(entry.getOriginalFile()); 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 ff612aa4d..8e2544946 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 @@ -571,8 +571,8 @@ public class StoryEntry extends IStoryPart { long usedMemory = runtime.totalMemory() - runtime.freeMemory(); long availableMemory = maxMemory - usedMemory; final boolean enoughMemory = options.outWidth * options.outHeight * 4L * 2L <= availableMemory; - if (!enoughMemory) { - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + if (!enoughMemory || Math.max(options.outWidth, options.outHeight) > 4200 || SharedConfig.getDevicePerformanceClass() <= SharedConfig.PERFORMANCE_CLASS_LOW) { +// options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inScaled = true; options.inDensity = options.outWidth; options.inTargetDensity = reqWidth; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java index b58a901f6..b39b37a7f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java @@ -879,7 +879,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification selectedUsers.addAll(selectedContacts); selectedUsersByGroup.putAll(selectedContactsByGroup); } - layoutManager.setReverseLayout(pageType == PAGE_TYPE_SHARE); + layoutManager.setReverseLayout(adapter.reversedLayout = pageType == PAGE_TYPE_SHARE); updateSpans(false); searchField.setText(""); searchField.setVisibility(pageType == PAGE_TYPE_SHARE ? View.GONE : View.VISIBLE); @@ -912,7 +912,9 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification sectionCell.setVisibility(View.GONE); // items.add(ItemInner.asPad(dp(84) + 4 * dp(56) + (sendAsMessageEnabled ? dp(120) : dp(64)))); items.add(ItemInner.asHeader2( - LocaleController.getString("StoryPrivacyAlertTitle", R.string.StoryPrivacyAlertTitle), + isEdit ? + LocaleController.getString("StoryPrivacyAlertEditTitle", R.string.StoryPrivacyAlertEditTitle) : + LocaleController.getString("StoryPrivacyAlertTitle", R.string.StoryPrivacyAlertTitle), storyPeriod != Integer.MAX_VALUE ? LocaleController.formatPluralString("StoryPrivacyAlertSubtitle", storyPeriod / 3600) : LocaleController.getString("StoryPrivacyAlertSubtitleProfile", R.string.StoryPrivacyAlertSubtitleProfile) @@ -1300,7 +1302,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification } else if (pageType == PAGE_TYPE_SEND_AS_MESSAGE) { button.setShowZero(true); button.setEnabled(!selectedUsers.isEmpty()); - button.setText(LocaleController.formatPluralString("StoryPrivacyButtonMessageChats", selectedUsers.size()), animated); +// button.setText(LocaleController.formatPluralString("StoryPrivacyButtonMessageChats", selectedUsers.size()), animated); button.setCount(selectedUsers.size(), animated); button2.setVisibility(View.GONE); } @@ -1536,6 +1538,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification } private RecyclerListView listView; + public boolean reversedLayout; @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { @@ -1587,8 +1590,8 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification } final ItemInner item = items.get(position); final int viewType = holder.getItemViewType(); - final ItemInner nextItem = position + 1 < items.size() ? items.get(position + 1) : null; - final boolean divider = nextItem != null && nextItem.viewType == viewType; + final ItemInner neighbour = reversedLayout ? (position > 0 ? items.get(position - 1) : null) : (position + 1 < items.size() ? items.get(position + 1) : null); + final boolean divider = neighbour != null && neighbour.viewType == viewType; if (viewType == VIEW_TYPE_USER) { UserCell userCell = (UserCell) holder.itemView; if (item.type > 0) { @@ -2539,7 +2542,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification } } - private static class HeaderCell2 extends FrameLayout { + private static class HeaderCell2 extends LinearLayout { private final Theme.ResourcesProvider resourcesProvider; private final TextView titleTextView; @@ -2547,27 +2550,19 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification public HeaderCell2(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + setOrientation(VERTICAL); this.resourcesProvider = resourcesProvider; titleTextView = new TextView(context); titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 16, 27, 0)); + addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 16, 27, 0)); subtitleTextView = new TextView(context); subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider)); subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - NotificationCenter.listenEmojiLoading(subtitleTextView); - addView(subtitleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 44, 27, 0)); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure( - MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(dp(72), MeasureSpec.EXACTLY) - ); + addView(subtitleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 5, 27, 13)); } public void setText(CharSequence title, CharSequence subtitle) { 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 2a9eecfae..a7b390131 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 @@ -106,6 +106,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.Bulletin; @@ -460,6 +461,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } if (outputEntry != null) { + if (wasSend && outputEntry.isEdit) { + outputEntry.editedMedia = false; + } outputEntry.destroy(false); outputEntry = null; } @@ -561,6 +565,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private void onOpenDone() { isShown = true; + wasSend = false; if (openType == 1) { previewContainer.setAlpha(1f); previewContainer.setTranslationX(0); @@ -1303,7 +1308,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private FrameLayout navbarContainer; private ImageView backButton; - private TextView titleTextView; + private SimpleTextView titleTextView; private StoryPrivacyBottomSheet privacySheet; /* PAGE_CAMERA */ @@ -1609,16 +1614,18 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg }); actionBarContainer.addView(backButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.LEFT)); - titleTextView = new TextView(context); - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleTextView = new SimpleTextView(context); + titleTextView.setTextSize(20); titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); titleTextView.setTextColor(0xffffffff); titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setText(LocaleController.getString("RecorderNewStory", R.string.RecorderNewStory)); - titleTextView.setShadowLayer(dpf2(1), 0, 1, 0x40000000); + titleTextView.getPaint().setShadowLayer(dpf2(1), 0, 1, 0x40000000); titleTextView.setAlpha(0f); titleTextView.setVisibility(View.GONE); - actionBarContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.TOP | Gravity.FILL_HORIZONTAL, 71, 0, 96, 0)); + titleTextView.setEllipsizeByGradient(true); + titleTextView.setRightPadding(AndroidUtilities.dp(96)); + actionBarContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.TOP | Gravity.FILL_HORIZONTAL, 71, 0, 0, 0)); downloadButton = new DownloadButton(context, () -> { applyFilter(); @@ -1626,7 +1633,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg }, currentAccount, windowView, resourcesProvider); actionBarContainer.addView(downloadButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT)); - muteHint = new HintView2(activity, HintView2.DIRECTION_TOP).setJoint(1, -68).setDuration(2000); + muteHint = new HintView2(activity, HintView2.DIRECTION_TOP) + .setJoint(1, -68) + .setDuration(2000) + .setBounce(false) + .setAnimatedTextHacks(true, true, false); muteHint.setPadding(dp(8), 0, dp(8), 0); actionBarContainer.addView(muteHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 52, 0, 0)); @@ -1640,7 +1651,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg return; } outputEntry.muted = !outputEntry.muted; - muteHint.setText(outputEntry.muted ? LocaleController.getString("StorySoundMuted") : LocaleController.getString("StorySoundNotMuted"), true); + muteHint.setText(outputEntry.muted ? LocaleController.getString("StorySoundMuted") : LocaleController.getString("StorySoundNotMuted"), muteHint.shown()); muteHint.show(); setIconMuted(outputEntry.muted, true); previewView.mute(outputEntry.muted); @@ -1703,8 +1714,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg savedDualHint = new HintView2(activity, HintView2.DIRECTION_RIGHT) .setJoint(0, 56 / 2) .setDuration(5000) - .setMultilineText(true) - .setMaxWidth(140); + .setMultilineText(true); actionBarContainer.addView(savedDualHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 52, 0)); videoTimerView = new VideoTimerView(context); @@ -1756,7 +1766,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg navbarContainer.addView(modeSwitcherView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); hintTextView = new HintTextView(context); - navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 66, 0, 66, 8)); + navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 8, 0, 8, 8)); previewButtons = new PreviewButtons(context); previewButtons.setVisibility(View.GONE); @@ -1791,6 +1801,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg .isEdit(false) .setWarnUsers(getUsersFrom(captionEdit.getText())) .whenSelectedRules((privacy, allowScreenshots, keepInProfile, whenDone) -> { + if (outputEntry == null) { + return; + } previewView.updatePauseReason(5, true); if (whenDone != null) { whenDone.run(); @@ -1837,7 +1850,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg trash = new TrashView(context); trash.setAlpha(0f); trash.setVisibility(View.GONE); - previewContainer.addView(trash, LayoutHelper.createFrame(120, 120, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 16)); + previewContainer.addView(trash, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 16)); previewHighlight = new PreviewHighlightView(context, currentAccount, resourcesProvider); previewContainer.addView(previewHighlight, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); @@ -2899,6 +2912,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg if (isVideo) { muteButton.setVisibility(View.VISIBLE); setIconMuted(outputEntry != null && outputEntry.muted, false); + titleTextView.setRightPadding(AndroidUtilities.dp(96)); + } else { + titleTextView.setRightPadding(AndroidUtilities.dp(48)); } downloadButton.setVisibility(View.VISIBLE); // privacySelector.setVisibility(View.VISIBLE); @@ -3173,13 +3189,13 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg paintViewBitmap.recycle(); paintViewBitmap = null; } - if (outputEntry.isDraft && outputEntry.paintFile != null) { + if (outputEntry != null && outputEntry.isDraft && outputEntry.paintFile != null) { paintViewBitmap = BitmapFactory.decodeFile(outputEntry.paintFile.getPath()); } if (paintViewBitmap == null) { paintViewBitmap = Bitmap.createBitmap(size.first, size.second, Bitmap.Config.ARGB_8888); } - paintView = new PaintView(activity, windowView, activity, currentAccount, paintViewBitmap, null, previewView.getOrientation(), outputEntry.mediaEntities, previewContainer.getMeasuredWidth(), previewContainer.getMeasuredHeight(), new MediaController.CropState(), null, resourcesProvider) { + paintView = new PaintView(activity, windowView, activity, currentAccount, paintViewBitmap, null, previewView.getOrientation(), outputEntry == null ? null : outputEntry.mediaEntities, previewContainer.getMeasuredWidth(), previewContainer.getMeasuredHeight(), new MediaController.CropState(), null, resourcesProvider) { @Override public void onEntityDraggedTop(boolean value) { previewHighlight.show(true, value, actionBarContainer); @@ -3673,7 +3689,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg return; } if (savedDualHint != null) { - savedDualHint.setText(isFrontface() ? LocaleController.getString(R.string.StoryCameraSavedDualBackHint) : LocaleController.getString(R.string.StoryCameraSavedDualFrontHint)); + CharSequence text = isFrontface() ? LocaleController.getString(R.string.StoryCameraSavedDualBackHint) : LocaleController.getString(R.string.StoryCameraSavedDualFrontHint); + savedDualHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, savedDualHint.getTextPaint())); + savedDualHint.setText(text); savedDualHint.show(); MessagesController.getGlobalMainSettings().edit().putInt("storysvddualhint", MessagesController.getGlobalMainSettings().getInt("storysvddualhint", 0) + 1).apply(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TrashView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TrashView.java index 2b73202c3..7662d173d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TrashView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TrashView.java @@ -60,7 +60,7 @@ public class TrashView extends View { textDrawable = new AnimatedTextView.AnimatedTextDrawable(true, true, false); textDrawable.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT); - textDrawable.setOverrideFullWidth(dp(120)); + textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); textDrawable.setTextSize(dp(14)); textDrawable.setTextColor(0xffffffff); textDrawable.setShadowLayer(dpf2(1.33f), 0, dp(1), 0x40000000); @@ -95,7 +95,7 @@ public class TrashView extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(dp(120), dp(120)); + setMeasuredDimension(widthMeasureSpec, dp(120)); } public void onDragInfo(boolean dragged, boolean deleted) { diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_arrow_mediabold.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_arrow_mediabold.png new file mode 100644 index 0000000000000000000000000000000000000000..55ade156b0adbf2adfd19b6346aebb9f30155869 GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlfU?euhU4DsMi zPLN<-tk@vO^#A{Vf2K!O3Tf`s7ti1~nIhV;pV^QjhdF6h#3g1kIj0L}CY@|PCgk>| zgK<}nsD@gzUSIQl29f^eQ*W6r?d$33*}tI1hbzOvTHro=Qjw$fu9ZF+OgavB^0Oo~ zW8_MX-e}@TX%yS#B=bjQL4{VxJDmw-3~U$0WwJbl+1e6ygDm9OH)(#fT=jH|*`B6p zdhU8!E2MQcI56$nC)2T<(eUdbnY14owkFOD41a7t%c$IOsRnt*)78&qol`;+0Ps*? A!T#RxYC55X#Hnz#LB?+8ZI&0wxHb&ku_DAvx(hUu1(<+#Fm+w@K zYd$38_T&TW#>REC7?=FHc=Y3kn~gjUA7Ln=Ger z&sUoCv|-;?mPh^$JWOX*q#OL1FF2$ej{dMxH8Sso6yGPU3t!tCBv@8R>ue}sk;>sd hB53eW!&ZukhoQx8?&95R*31Dp+|$+1Wt~$(699^xUOE5( literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediabold.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediabold.png new file mode 100644 index 0000000000000000000000000000000000000000..27b56ebb62ac6fbdbd3442c045c7a6019439ed46 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uuz(rC1}QWNE&K$enmk<`Lo5W7 z6D0mU`2YWZor8|&H2+4anGHW|1@5yaRTl9UGG+bqGIo|oJjZlv0ei}K2198do?bDA zPo<4Nc$JkGTln;`9%H!l#(^iO7%hin7W^M vi0IN;ju(H-(wUujjwP#)G09b;Ug8piFMoD@l+d?!kgGgh{an^LB{Ts59dAoE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediathin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_arrow_mediathin.png new file mode 100644 index 0000000000000000000000000000000000000000..8f97d68d31ed3b2ab1e288411ef4c7d9c2b84bd9 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uuz(rC1}QWNE&K$esy$sCLo5W7 z6D0mU`2YX^EQd3W+x#16`7?a9Q+TFyT3~@2t3sWFv9mFVdQ&MBb@01`h)@Bjb+ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediabold.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediabold.png new file mode 100644 index 0000000000000000000000000000000000000000..84309b95f1b05b5f663b8764c82d8287b3ab3dbf GIT binary patch literal 394 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZp6?zIeJghD2~C zCrGd^Ry2@ea<*mp_y7NV?jy?^E#|(fV~je*dBna!f-Q^vkYIb_Hs{P=R!kWySp?$c zOOH(8I&OrHT0Q|DlGMN`25ev$Y@)m#ft{PScW6)SvR_<{?HImZjN-|yS8H4D(8l2JyCxD6WEU`UbyCa!i@Rmm(Jo9 zPZzxUVLplZMY^R9E3bP0l+XkK!83m@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediathin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_arrow_mediathin.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd88dde79734094b988f235a36ff034c4d5f401 GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZp6?9(cMqhD2~C zCrGd^Ry2@ea<*mp_y7NT#v`Q;YYY_X7^C)xb~rv@70AAHSJ1(`*kPOV!3N7klFyhF zY+rFiB=Gc3NH{VztMT3h_EVh?C#fsUW1QmOw5pPK$y!NC$$a4p%@f$76gB0F2&*1?o%lC9~49Q@9 zJ8h$vv!O^^_0&bK1zLQpbMIPnT4`EX{9v+kasQ}zr-sq-1M4q_SeZF@VwQ+p30(2u zQORGviiIsEE4THUf0DPjqw@UOlmGuGx0py7X)3TTX%Lyf6!c)ecEGe$ar*yOj0K2@G$-T5BFzpJ_WH!gNekTPVEkMsno@h96pWj};S~l_tJ%a>xx;nt5ws zYY3t)zCSNF#&8HWY-j!8bZzopr0F`^m4gdfE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_arrow_mediathin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_arrow_mediathin.png new file mode 100644 index 0000000000000000000000000000000000000000..aa4ee11df5278dabaaf0b99d6503fdca081dfc7f GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~ySip>6gB0F2&*1?obM$m^49Q@9 zJI&XN*-@bNveTW8XH2tN1-|PQ_q=(mXw#70`rzKw9lTGNZl-G9tZEcEp~_@c$1B+O z@@M9(nM=}ZSovppg+ARI?rXevo)g~*MoR_uCk-+am_J%gP&sKD(WGzCIX#on*kgb5 z{vXdi1O!M;vEzQlmA~o#_r{LQA05i&PT$ya9IdkMyDZ+6P{;krWlNT@(8U*~A7$@- zeI4>z_;q$xK0;7H&L^h7SF9HHrlAVV|w@li#SqA81IpYSt1ll=Bpv0k8{zd`m!v-<4pScf|d lzi+OYz+B`2@u}6*1NyR$7OtGYsQwHTsGhEVF6*2UngDFwuA~3} literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/raw/camera_frag.glsl b/TMessagesProj/src/main/res/raw/camera_frag.glsl index 085b0c6ca..7cca4725e 100644 --- a/TMessagesProj/src/main/res/raw/camera_frag.glsl +++ b/TMessagesProj/src/main/res/raw/camera_frag.glsl @@ -8,9 +8,6 @@ uniform vec2 pixelWH; uniform float roundRadius; uniform float scale; uniform float alpha; -uniform float crossfade; -uniform mat4 cameraMatrix; -uniform mat4 oppositeCameraMatrix; uniform float shapeFrom, shapeTo, shapeT; uniform float dual; uniform float blur; @@ -33,17 +30,6 @@ float scene() { mix(abs(a)<.1 ? R : rr, abs(b)<.1 ? R : rr, shapeT) ) * pixelWH.x; } -vec4 BilinearTextureSample(vec2 P) { - vec2 onePixel = 1.0 / pixelWH, twoPixels = 2. * onePixel; - vec2 pixel = P * pixelWH + .5; - vec2 frac = fract(pixel); - pixel = (floor(pixel) / pixelWH) - onePixel / 2.; - return mix( - mix(texture2D(sTexture, pixel + vec2(0., 0.) * onePixel), texture2D(sTexture, pixel + vec2(1., 0.) * onePixel), frac.x), - mix(texture2D(sTexture, pixel + vec2(0., 1.) * onePixel), texture2D(sTexture, pixel + vec2(1., 1.) * onePixel), frac.x), - frac.y - ); -} vec4 makeblur() { vec2 S = 4. * vec2(1., pixelWH.x / pixelWH.y); vec2 st = fract(uv * S); @@ -61,14 +47,14 @@ vec4 program() { float dalpha = clamp(1. - scene(), 0., 2.) / 2. * alpha; if (dalpha <= 0.) return vec4(0.); - + if (blur >= 1.) return makeblur(); else if (blur <= 0.) - return (dual > .5 ? BilinearTextureSample(uv) : texture2D(sTexture, uv)) * vec4(1., 1., 1., dalpha); + return texture2D(sTexture, uv) * vec4(1., 1., 1., dalpha); else - return mix((dual > .5 ? BilinearTextureSample(uv) : texture2D(sTexture, uv)), makeblur(), blur) * vec4(1., 1., 1., dalpha); + return mix(texture2D(sTexture, uv), makeblur(), blur) * vec4(1., 1., 1., dalpha); } void main() { - gl_FragColor = program(); + gl_FragColor = dual < .5 ? texture2D(sTexture, uv) : program(); } \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 9957dce06..f8fb4486e 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -709,6 +709,7 @@ Link Tap to add a permanent link Choose photo + Add Image Choose photo or video Set new photo Take photo @@ -1044,11 +1045,10 @@ recommended Advertiser Info What are sponsored\nmessages? - Unlike other apps, Telegram never uses your private data to target ads. **Learn more in the Privacy Policy** - Unlike other apps, Telegram never uses your private data to target ads. You are seeing this message only because someone chose this public one-to-many channel as a space to promote their messages. This means that no user data is mined or analyzed to display ads, and every user viewing a channel on Telegram sees the same sponsored message. - Unlike other apps, Telegram doesn\'t track whether you tapped on a sponsored message and doesn\'t profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties can’t spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that. - Telegram offers free and unlimited service to hundreds of millions of users, which involves significant server and traffic costs. In order to remain independent and stay true to its values, Telegram developed a paid tool to promote messages with user privacy in mind. We welcome responsible advertisers at: - Ads should no longer be synonymous with abuse of user privacy. Let us redefine how a tech company should operate – together. + Unlike other apps, Telegram never uses your private data to target ads. [Learn more in the Privacy Policy](https://telegram.org/privacy#5-6-no-ads-based-on-user-data) + Unlike other apps, Telegram doesn\'t track whether you tapped on a sponsored message and doesn\'t profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties can’t spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that. + Telegram offers free and unlimited service to hundreds of millions of users, which involves significant server and traffic costs. In order to remain independent and stay true to its values, Telegram developed a paid tool to promote messages with user privacy in mind. We welcome responsible advertisers at: + Ads should no longer be synonymous with abuse of user privacy. Let us redefine how a tech company should operate – together. Sponsored messages See https://telegram.org LEARN MORE @@ -6732,6 +6732,7 @@ Contacts (-%d) Contacts (-%d) Share story + Edit Privacy Settings Choose who can view for %d hours Choose who can view for %d hour Choose who can view for %d hours @@ -6749,30 +6750,8 @@ Choose recipients Save Settings Post Story - Share with Close Friends Save List - Share with All Contacts - Share with Contacts - Share with Contact - Share with Contacts - Share with Contacts - Share with Contacts - Share with Contacts - Share with Selected Contacts - Share with Selected Contact - Share with Selected Contacts - Share with Selected Contacts - Share with Selected Contacts - Share with Selected Contacts Exclude Contacts - Share with Everyone - Send as Message - Send to Selected Chats - Send to Selected Chat - Send to Selected Chats - Send to Selected Chats - Send to Selected Chats - Send to Selected Chats Everyone Contacts exclude people @@ -6808,11 +6787,6 @@ Archive Stories Archive Stories Edit Story - Edit Photo - Edit Video - Edit Caption - Replace Photo - Replace Video Who can see Everyone Close Friends @@ -6906,6 +6880,7 @@ %d stories were posted %d stories were posted %d stories were posted + posted a story posted %d stories posted a story posted %d stories @@ -6962,7 +6937,7 @@ View Story The story you were mentioned in is no longer available The story where you mentioned %s is no longer available - **You** mentioned %s in a story. + You mentioned %s in a story. Stories cached story Stories @@ -7026,6 +7001,6 @@ You can’t post more than **%d stories** in **24 hours**. You can’t post more than **%d stories** in **24 hours**. Posting stories is currently available only to subscribers of **Telegram Premium**. - Hide Stories + Hide Stories Unhide Stories diff --git a/gradle.properties b/gradle.properties index f59208bd5..71be4947c 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=3687 -APP_VERSION_NAME=9.7.0 +APP_VERSION_CODE=3705 +APP_VERSION_NAME=9.7.2 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=android RELEASE_KEY_ALIAS=androidkey