From 5dd649197b48e5b2ad9ae91dcc8dc87548aa877c Mon Sep 17 00:00:00 2001 From: dkaraush Date: Tue, 6 Feb 2024 20:34:03 +0400 Subject: [PATCH] update to 10.6.4 (4365) --- .../jni/tgnet/ConnectionsManager.cpp | 2 +- .../src/main/assets/bluebubbles.attheme | 2 +- .../src/main/assets/darkblue.attheme | 5 +- TMessagesProj/src/main/assets/night.attheme | 5 +- .../widget/ChatListItemAnimator.java | 2 +- .../widget/DefaultItemAnimator.java | 2 +- .../SQLite/SQLitePreparedStatement.java | 4 - .../telegram/messenger/AndroidUtilities.java | 4 + .../telegram/messenger/ApplicationLoader.java | 5 - .../ChatMessagesMetadataController.java | 2 +- .../messenger/DatabaseMigrationHelper.java | 20 +- .../telegram/messenger/DocumentObject.java | 2 +- .../telegram/messenger/FileLoadOperation.java | 2 +- .../org/telegram/messenger/FileLoader.java | 2 +- .../java/org/telegram/messenger/FileLog.java | 4 +- .../telegram/messenger/FileRefController.java | 1 + .../telegram/messenger/LocaleController.java | 25 + .../telegram/messenger/MediaController.java | 9 +- .../messenger/MediaDataController.java | 470 ++- .../org/telegram/messenger/MessageObject.java | 176 +- .../messenger/MessagesController.java | 330 ++- .../telegram/messenger/MessagesStorage.java | 425 ++- .../messenger/NotificationCenter.java | 6 +- .../messenger/SavedMessagesController.java | 166 +- .../messenger/SendMessagesHelper.java | 14 +- .../org/telegram/messenger/SharedConfig.java | 16 - .../telegram/messenger/TopicsController.java | 4 +- .../org/telegram/messenger/Utilities.java | 10 + .../messenger/VideoEncodingService.java | 31 +- .../video/VideoPlayerHolderBase.java | 52 +- .../telegram/tgnet/ConnectionsManager.java | 2 +- .../main/java/org/telegram/tgnet/TLRPC.java | 20 +- .../org/telegram/ui/ActionBar/ActionBar.java | 20 +- .../ui/ActionBar/ActionBarLayout.java | 12 + .../telegram/ui/ActionBar/ActionBarMenu.java | 7 + .../ui/ActionBar/ActionBarMenuItem.java | 19 +- .../ui/ActionBar/ActionBarMenuSubItem.java | 2 +- .../telegram/ui/ActionBar/AlertDialog.java | 24 +- .../ui/ActionBar/AlertDialogDecor.java | 9 +- .../telegram/ui/ActionBar/BackDrawable.java | 9 +- .../java/org/telegram/ui/ActionBar/OKLCH.java | 154 + .../java/org/telegram/ui/ActionBar/Theme.java | 4 +- .../telegram/ui/ActionBar/ThemeColors.java | 6 +- .../ui/Adapters/DialogsSearchAdapter.java | 4 +- .../ui/Adapters/MessagesSearchAdapter.java | 35 +- .../java/org/telegram/ui/ArticleViewer.java | 2 +- .../org/telegram/ui/CalendarActivity.java | 8 +- .../org/telegram/ui/Cells/AboutLinkCell.java | 22 +- .../telegram/ui/Cells/ChatMessageCell.java | 188 +- .../org/telegram/ui/Cells/DialogCell.java | 53 +- .../telegram/ui/Cells/ExpiredStoryView.java | 23 +- .../org/telegram/ui/Cells/StickerSetCell.java | 10 + .../java/org/telegram/ui/Cells/TextCell.java | 4 +- .../java/org/telegram/ui/ChatActivity.java | 2535 +++++++++++++---- .../telegram/ui/ChatActivityContainer.java | 19 +- .../ui/ChatReactionsEditActivity.java | 1 + .../org/telegram/ui/ChooseSpeedLayout.java | 2 +- .../ui/Components/AnimatedEmojiDrawable.java | 4 +- .../ui/Components/AnimatedTextView.java | 33 +- .../ui/Components/AudioPlayerAlert.java | 7 + .../ui/Components/BackupImageView.java | 4 + .../ui/Components/BlurredFrameLayout.java | 2 +- .../BottomSheetWithRecyclerListView.java | 2 +- .../org/telegram/ui/Components/Bulletin.java | 180 +- .../ui/Components/BulletinFactory.java | 67 +- .../ui/Components/ChatActivityEnterView.java | 66 +- .../ui/Components/ChatAvatarContainer.java | 79 +- .../ui/Components/ChatGreetingsView.java | 11 +- .../ChatScrimPopupContainerLayout.java | 39 +- .../telegram/ui/Components/CounterView.java | 35 +- .../ui/Components/EditTextBoldCursor.java | 1 + .../ui/Components/EditTextCaption.java | 32 +- .../telegram/ui/Components/EditTextEmoji.java | 5 + .../ui/Components/InstantCameraView.java | 2 +- .../telegram/ui/Components/MediaActivity.java | 55 +- .../ui/Components/MessagePreviewView.java | 6 +- .../ui/Components/MessagePrivateSeenView.java | 28 +- .../Paint/Views/MessageEntityView.java | 6 +- .../Premium/LimitReachedBottomSheet.java | 3 +- .../Premium/PremiumFeatureBottomSheet.java | 10 +- .../Premium/PremiumLockIconView.java | 18 + .../Components/Premium/StarParticlesView.java | 13 + .../Components/Premium/StoriesPageView.java | 5 + .../Premium/VideoScreenPreview.java | 7 +- .../boosts/UserSelectorBottomSheet.java | 9 +- .../ChatCustomReactionsEditActivity.java | 15 +- .../ChatSelectionReactionMenuOverlay.java | 6 +- .../Reactions/CustomEmojiReactionsWindow.java | 11 +- .../Reactions/ReactionsLayoutInBubble.java | 323 ++- .../Components/ReactionsContainerLayout.java | 416 ++- .../ui/Components/SearchTagsList.java | 752 ++++- .../telegram/ui/Components/ShareAlert.java | 8 +- .../ui/Components/SharedMediaLayout.java | 668 ++++- .../ui/Components/StickerEmptyView.java | 7 +- .../telegram/ui/Components/StickersAlert.java | 1 + .../telegram/ui/Components/ThanosEffect.java | 94 +- .../Components/spoilers/SpoilersTextView.java | 41 + .../java/org/telegram/ui/DialogsActivity.java | 30 +- .../telegram/ui/GroupCreateFinalActivity.java | 2 +- .../telegram/ui/GroupStickersActivity.java | 2 +- .../java/org/telegram/ui/LaunchActivity.java | 80 +- .../org/telegram/ui/PaymentFormActivity.java | 2 +- .../org/telegram/ui/PhotoPickerActivity.java | 2 +- .../java/org/telegram/ui/PhotoViewer.java | 65 +- .../telegram/ui/PremiumPreviewFragment.java | 34 +- .../telegram/ui/PrivacyControlActivity.java | 64 +- .../telegram/ui/PrivacySettingsActivity.java | 51 +- .../java/org/telegram/ui/ProfileActivity.java | 61 +- .../ui/SelectAnimatedEmojiDialog.java | 33 +- .../org/telegram/ui/StatisticActivity.java | 1 + .../telegram/ui/Stories/PeerStoriesView.java | 195 +- .../ui/Stories/ProfileStoriesView.java | 8 + .../ui/Stories/StoriesController.java | 8 +- .../org/telegram/ui/Stories/StoryViewer.java | 29 +- .../ui/Stories/recorder/GalleryListView.java | 3 +- .../ui/Stories/recorder/HintView2.java | 1 + .../ui/Stories/recorder/StoryRecorder.java | 2 +- .../org/telegram/ui/TopicCreateFragment.java | 4 +- .../java/org/telegram/ui/WebviewActivity.java | 1 + .../res/drawable-hdpi/menu_external_link.png | Bin 0 -> 581 bytes .../drawable-hdpi/menu_premium_privacy.png | Bin 0 -> 879 bytes .../res/drawable-hdpi/menu_premium_seen.png | Bin 0 -> 804 bytes .../res/drawable-hdpi/menu_premium_tools.png | Bin 0 -> 899 bytes .../res/drawable-hdpi/menu_quality_hd.png | Bin 0 -> 853 bytes .../res/drawable-hdpi/menu_quality_hd2.png | Bin 0 -> 876 bytes .../res/drawable-hdpi/menu_quality_sd.png | Bin 0 -> 993 bytes .../res/drawable-hdpi/menu_tag_delete.png | Bin 0 -> 1031 bytes .../main/res/drawable-hdpi/menu_tag_edit.png | Bin 0 -> 918 bytes .../res/drawable-hdpi/menu_tag_filter.png | Bin 0 -> 921 bytes .../main/res/drawable-hdpi/menu_tag_plus.png | Bin 0 -> 822 bytes .../res/drawable-hdpi/menu_tag_rename.png | Bin 0 -> 938 bytes .../res/drawable-hdpi/navbar_search_tag.png | Bin 0 -> 867 bytes .../main/res/drawable-hdpi/premium_tags.png | Bin 0 -> 802 bytes .../res/drawable-mdpi/menu_external_link.png | Bin 0 -> 435 bytes .../drawable-mdpi/menu_premium_privacy.png | Bin 0 -> 604 bytes .../res/drawable-mdpi/menu_premium_seen.png | Bin 0 -> 578 bytes .../res/drawable-mdpi/menu_premium_tools.png | Bin 0 -> 610 bytes .../res/drawable-mdpi/menu_quality_hd.png | Bin 0 -> 625 bytes .../res/drawable-mdpi/menu_quality_hd2.png | Bin 0 -> 617 bytes .../res/drawable-mdpi/menu_quality_sd.png | Bin 0 -> 636 bytes .../res/drawable-mdpi/menu_tag_delete.png | Bin 0 -> 695 bytes .../main/res/drawable-mdpi/menu_tag_edit.png | Bin 0 -> 628 bytes .../res/drawable-mdpi/menu_tag_filter.png | Bin 0 -> 628 bytes .../main/res/drawable-mdpi/menu_tag_plus.png | Bin 0 -> 611 bytes .../res/drawable-mdpi/menu_tag_rename.png | Bin 0 -> 601 bytes .../res/drawable-mdpi/navbar_search_tag.png | Bin 0 -> 668 bytes .../main/res/drawable-mdpi/premium_tags.png | Bin 0 -> 554 bytes .../res/drawable-xhdpi/menu_external_link.png | Bin 0 -> 700 bytes .../drawable-xhdpi/menu_premium_privacy.png | Bin 0 -> 1125 bytes .../res/drawable-xhdpi/menu_premium_seen.png | Bin 0 -> 1078 bytes .../res/drawable-xhdpi/menu_premium_tools.png | Bin 0 -> 1147 bytes .../res/drawable-xhdpi/menu_quality_hd.png | Bin 0 -> 1159 bytes .../res/drawable-xhdpi/menu_quality_hd2.png | Bin 0 -> 1120 bytes .../res/drawable-xhdpi/menu_quality_sd.png | Bin 0 -> 1363 bytes .../res/drawable-xhdpi/menu_tag_delete.png | Bin 0 -> 1373 bytes .../main/res/drawable-xhdpi/menu_tag_edit.png | Bin 0 -> 1232 bytes .../res/drawable-xhdpi/menu_tag_filter.png | Bin 0 -> 1252 bytes .../main/res/drawable-xhdpi/menu_tag_plus.png | Bin 0 -> 1111 bytes .../res/drawable-xhdpi/menu_tag_rename.png | Bin 0 -> 1324 bytes .../res/drawable-xhdpi/navbar_search_tag.png | Bin 0 -> 1236 bytes .../main/res/drawable-xhdpi/premium_tags.png | Bin 0 -> 1065 bytes .../drawable-xxhdpi/menu_external_link.png | Bin 0 -> 935 bytes .../drawable-xxhdpi/menu_premium_privacy.png | Bin 0 -> 1632 bytes .../res/drawable-xxhdpi/menu_premium_seen.png | Bin 0 -> 1564 bytes .../drawable-xxhdpi/menu_premium_tools.png | Bin 0 -> 1471 bytes .../res/drawable-xxhdpi/menu_quality_hd.png | Bin 0 -> 1601 bytes .../res/drawable-xxhdpi/menu_quality_hd2.png | Bin 0 -> 1576 bytes .../res/drawable-xxhdpi/menu_quality_sd.png | Bin 0 -> 1963 bytes .../res/drawable-xxhdpi/menu_tag_delete.png | Bin 0 -> 2070 bytes .../res/drawable-xxhdpi/menu_tag_edit.png | Bin 0 -> 1740 bytes .../res/drawable-xxhdpi/menu_tag_filter.png | Bin 0 -> 1769 bytes .../res/drawable-xxhdpi/menu_tag_plus.png | Bin 0 -> 1418 bytes .../res/drawable-xxhdpi/menu_tag_rename.png | Bin 0 -> 1980 bytes .../res/drawable-xxhdpi/navbar_search_tag.png | Bin 0 -> 1635 bytes .../main/res/drawable-xxhdpi/premium_tags.png | Bin 0 -> 1574 bytes .../src/main/res/raw/options_to_search.json | 1 + .../src/main/res/raw/premium_object_check.svg | 7 + .../src/main/res/raw/premium_object_star.svg | 7 + .../src/main/res/raw/premium_object_tag.svg | 7 + .../src/main/res/raw/tag_icon_3.json | 1 + TMessagesProj/src/main/res/values/strings.xml | 72 +- gradle.properties | 4 +- 182 files changed, 7043 insertions(+), 1797 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_tag_plus.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_tag_rename.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_premium_privacy.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_premium_tools.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd2.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_tag_plus.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_tag_rename.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_privacy.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd2.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_edit.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_filter.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_plus.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_rename.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/navbar_search_tag.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/premium_tags.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_seen.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_tools.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_filter.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_rename.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/navbar_search_tag.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png create mode 100644 TMessagesProj/src/main/res/raw/options_to_search.json create mode 100644 TMessagesProj/src/main/res/raw/premium_object_check.svg create mode 100644 TMessagesProj/src/main/res/raw/premium_object_star.svg create mode 100644 TMessagesProj/src/main/res/raw/premium_object_tag.svg create mode 100644 TMessagesProj/src/main/res/raw/tag_icon_3.json diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 8df45c39e..94e97c4f7 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -2390,7 +2390,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t } } if (request->retryCount >= retryMax) { - if (LOGS_ENABLED) DEBUG_E("timed out %s", typeInfo.name()); + if (LOGS_ENABLED) DEBUG_E("timed out %s, message_id = 0x%" PRIx64, typeInfo.name(), request->messageId); auto error = new TL_error(); error->code = -123; error->text = "RETRY_LIMIT"; diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index 6e29f76c9..bb94402b0 100644 --- a/TMessagesProj/src/main/assets/bluebubbles.attheme +++ b/TMessagesProj/src/main/assets/bluebubbles.attheme @@ -49,7 +49,7 @@ chat_inReplyNameText=-14643754 chats_onlineCircle=-13192972 chat_outAudioSelectedProgress=-7484939 chat_inInstant=-14707230 -avatar_backgroundSaved=-10438409 +avatar_backgroundSaved=-9847303 chats_sentReadCheck=-15754010 chats_nameMessageArchived=-7237231 chat_outSentCheckSelected=-14968350 diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index 8c3eda0ba..314ab31cd 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -9,6 +9,9 @@ windowBackgroundWhiteBlueIcon=-528890628 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14273984 actionBarActionModeDefaultTop=-14536643 +actionBarActionModeReaction=318767103 +actionBarActionModeReactionText=-1 +actionBarActionModeReactionDot=-13287865 statisticChartHintLine=452984831 chats_menuPhone=-1816080163 chat_outViews=-7357217 @@ -425,7 +428,7 @@ chats_attachMessage=-8548712 chat_topPanelBackground=-14602949 chat_outSentClock=-8213557 dialogBackgroundGray=-14932431 -chat_searchPanelText=-8796932 +chat_searchPanelText=-1 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=857487708 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 46217ff1c..5962858d6 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -8,6 +8,9 @@ chat_inSentClockSelected=-7490861 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14211289 actionBarActionModeDefaultTop=-14277082 +actionBarActionModeReaction=318767103 +actionBarActionModeReactionText=-1 +actionBarActionModeReactionDot=-13287865 statisticChartHintLine=452984831 chats_menuPhone=-1815557944 chat_outViews=-7357217 @@ -450,7 +453,7 @@ chats_attachMessage=-8224126 chat_topPanelBackground=-15066597 chat_outSentClock=-6698513 dialogBackgroundGray=-14013910 -chat_searchPanelText=-10767620 +chat_searchPanelText=-1 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=859062986 diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java index 765c7c3cf..2c542e65e 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java @@ -990,7 +990,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { return true; } - void animateChangeImpl(final ChangeInfo changeInfo) { + public void animateChangeImpl(final ChangeInfo changeInfo) { final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index 5d923a3a6..b351c8746 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -468,7 +468,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { return true; } - void animateChangeImpl(final ChangeInfo changeInfo) { + public void animateChangeImpl(final ChangeInfo changeInfo) { final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index 40b1145a8..cef386c19 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -25,7 +25,6 @@ public class SQLitePreparedStatement { private long startTime; private String query; - //private static HashMap hashMap; public long getStatementHandle() { return sqliteStatementHandle; @@ -112,9 +111,6 @@ public class SQLitePreparedStatement { } } try { - /*if (BuildVars.DEBUG_PRIVATE_VERSION) { - hashMap.remove(this); - }*/ isFinalized = true; finalize(sqliteStatementHandle); } catch (SQLiteException e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index a09a3d127..39409bd5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -73,6 +73,7 @@ import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.DisplayMetrics; +import android.util.Log; import android.util.Pair; import android.util.StateSet; import android.util.TypedValue; @@ -155,6 +156,7 @@ import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.PipVideoOverlay; +import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.TypefaceSpan; @@ -314,6 +316,7 @@ public class AndroidUtilities { }; public static final String STICKERS_PLACEHOLDER_PACK_NAME = "tg_placeholders_android"; + public static final String STICKERS_PLACEHOLDER_PACK_NAME_2 = "tg_superplaceholders_android_2"; private static boolean containsUnsupportedCharacters(String text) { if (text.contains("\u202C")) { @@ -4441,6 +4444,7 @@ public class AndroidUtilities { } public static void makeAccessibilityAnnouncement(CharSequence what) { + if (TextUtils.isEmpty(what)) return; AccessibilityManager am = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); if (am.isEnabled()) { AccessibilityEvent ev = AccessibilityEvent.obtain(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index f427f8ab3..3d09a03c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -429,11 +429,6 @@ public class ApplicationLoader extends Application { return false; } - public static boolean useLessData() { - ensureCurrentNetworkGet(); - return BuildVars.DEBUG_PRIVATE_VERSION && (SharedConfig.forceLessData || isConnectionSlow()); - } - public static boolean isConnectionSlow() { try { ensureCurrentNetworkGet(false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java index 9841be6e2..3a65cc5bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java @@ -23,7 +23,7 @@ public class ChatMessagesMetadataController { } public void checkMessages(ChatActivity.ChatActivityAdapter chatAdapter, int maxAdapterPosition, int minAdapterPosition, long currentTime) { - ArrayList messages = chatActivity.messages; + ArrayList messages = chatAdapter.getMessages(); if (!chatActivity.isInScheduleMode() && maxAdapterPosition >= 0 && minAdapterPosition >= 0) { int from = minAdapterPosition - chatAdapter.messagesStartRow - 10; int to = maxAdapterPosition - chatAdapter.messagesStartRow + 10; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 497231fe7..72d9b9897 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1409,10 +1409,22 @@ public class DatabaseMigrationHelper { version = 138; } - if (version == 138) { - database.executeFast("CREATE TABLE IF NOT EXISTS saved_reaction_tags (data BLOB);").stepThis().dispose(); - database.executeFast("PRAGMA user_version = 139").stepThis().dispose(); - version = 139; + if (version == 138 || version == 139 || version == 140 || version == 141) { + database.executeFast("DROP TABLE IF EXISTS tag_message_id;").stepThis().dispose(); + database.executeFast("CREATE TABLE tag_message_id(mid INTEGER, topic_id INTEGER, tag INTEGER, text TEXT);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_idx_tag_message_id ON tag_message_id(tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_text_idx_tag_message_id ON tag_message_id(tag, text);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_idx_tag_message_id ON tag_message_id(topic_id, tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_text_idx_tag_message_id ON tag_message_id(topic_id, tag, text);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 142").stepThis().dispose(); + version = 142; + } + + if (version == 142) { + database.executeFast("DROP TABLE IF EXISTS saved_reaction_tags;").stepThis().dispose(); + database.executeFast("CREATE TABLE saved_reaction_tags (topic_id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 143").stepThis().dispose(); + version = 143; } return version; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java index 10ce54144..189740c2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java @@ -53,7 +53,7 @@ public class DocumentObject { TLRPC.PhotoSize photoSize = sizes.get(a); if (photoSize instanceof TLRPC.TL_photoPathSize) { photoPathSize = (TLRPC.TL_photoPathSize) photoSize; - } else { + } else if (photoSize instanceof TLRPC.TL_photoSize) { w = photoSize.w; h = photoSize.h; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d1de09781..d07867269 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -2441,7 +2441,7 @@ public class FileLoadOperation { } }, null, null, flags, datacenterId, connectionType, isLast); if (BuildVars.LOGS_ENABLED) { - FileLog.d("debug_loading: " + cacheFileFinal.getName() + " dc=" + datacenterId + " send reqId " + requestInfo.requestToken + " offset=" + requestInfo.offset + " conType=" + connectionType + " priority="); + FileLog.d("debug_loading: " + cacheFileFinal.getName() + " dc=" + datacenterId + " send reqId " + requestInfo.requestToken + " offset=" + requestInfo.offset + " conType=" + connectionType + " priority=" + priority); } requestsCount++; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 0fe68a6fa..02d68cfd2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -984,7 +984,7 @@ public class FileLoader extends BaseController { 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); + FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount + " cacheType=" + cacheType); } return operation; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index b5cac6c33..4ddee0a30 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -75,7 +75,7 @@ public class FileLog { private static Gson gson; private static HashSet excludeRequests; - public static void dumpResponseAndRequest(TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) { + public static void dumpResponseAndRequest(int account, TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) { if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || request == null) { return; } @@ -97,7 +97,7 @@ public class FileLog { long time = System.currentTimeMillis(); FileLog.getInstance().logQueue.postRunnable(() -> { try { - String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + (System.currentTimeMillis() - startRequestTimeInMillis) + " request_token=" + requestToken; + String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + (System.currentTimeMillis() - startRequestTimeInMillis) + " request_token=" + requestToken + " account=" + account; FileLog.getInstance().tlStreamWriter.write(getInstance().dateFormat.format(time) + " " + metadata); FileLog.getInstance().tlStreamWriter.write("\n"); FileLog.getInstance().tlStreamWriter.write(req); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 63cd043c9..44a0fde3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -1,6 +1,7 @@ package org.telegram.messenger; import android.os.SystemClock; +import android.util.Log; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index e5529442f..c68b0c0b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -1722,6 +1722,31 @@ public class LocaleController { return "LOC_ERR"; } + public static String formatPmSeenDate(long date) { + try { + date *= 1000; + Calendar rightNow = Calendar.getInstance(); + int day = rightNow.get(Calendar.DAY_OF_YEAR); + int year = rightNow.get(Calendar.YEAR); + rightNow.setTimeInMillis(date); + int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); + int dateYear = rightNow.get(Calendar.YEAR); + + if (dateDay == day && year == dateYear) { + return LocaleController.formatString(R.string.PmReadTodayAt, getInstance().formatterDay.format(new Date(date))); + } else if (dateDay + 1 == day && year == dateYear) { + return LocaleController.formatString(R.string.PmReadYesterdayAt, getInstance().formatterDay.format(new Date(date))); + } else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) { + return LocaleController.formatString(R.string.PmReadDateTimeAt, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date))); + } else { + return LocaleController.formatString(R.string.PmReadDateTimeAt, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date))); + } + } catch (Exception e) { + FileLog.e(e); + } + return "LOC_ERR"; + } + public static String formatShortDate(long date) { try { date *= 1000; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 6bf995be4..5c6fc9a97 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -54,7 +54,6 @@ import android.provider.OpenableColumns; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.view.HapticFeedbackConstants; @@ -84,6 +83,7 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.EmbedBottomSheet; import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.PipRoundVideoView; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; @@ -2397,10 +2397,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, //TODO topics if (!playlistEndReached[0]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0, null, null); } else if (playlistMergeDialogId != 0 && !playlistEndReached[1]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0, null, null); } } @@ -5572,6 +5572,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, final String query; final FiltersView.MediaFilterData filter; final long dialogId; + public long topicId; final long minDate; final long maxDate; public int totalCount; @@ -5579,6 +5580,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, public int nextSearchRate; public int folderId; + public ReactionsLayoutInBubble.VisibleReaction reaction; + public PlaylistGlobalSearchParams(String query, long dialogId, long minDate, long maxDate, FiltersView.MediaFilterData filter) { this.filter = filter; this.query = query; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 0db5b6b0b..156c5ca78 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -60,10 +60,12 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.EmojiThemes; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.QuoteSpan; @@ -566,7 +568,7 @@ public class MediaDataController extends BaseController { boolean forceReload = false; if (bots != null) { if (!cache) { - getMessagesStorage().putUsersAndChats(bots.users, null, true, false); + getMessagesStorage().putUsersAndChats(bots.users, null, true, true); } getMessagesController().putUsers(bots.users, cache); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.attachMenuBotsDidLoad)); @@ -1199,6 +1201,31 @@ public class MediaDataController extends BaseController { return null; } + public void setPlaceholderImage(BackupImageView imageView, String setName, String emoji, String filter) { + TLRPC.InputStickerSet inputStickerSet = new TLRPC.TL_inputStickerSetShortName(); + inputStickerSet.short_name = setName; + MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSet, 0, false, set -> { + if (set == null) return; + TLRPC.Document document = null; + for (int i = 0; i < set.packs.size(); ++i) { + if (!set.packs.get(i).documents.isEmpty() && TextUtils.equals(set.packs.get(i).emoticon, emoji)) { + long documentId = set.packs.get(i).documents.get(0); + for (int j = 0; j < set.documents.size(); ++j) { + if (set.documents.get(j).id == documentId) { + document = set.documents.get(j); + break; + } + } + break; + } + } + if (document != null) { + Drawable thumbDrawable = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, 1f, null); + imageView.setImage(ImageLocation.getForDocument(document), filter, thumbDrawable, 0, document); + } + }); + } + public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputStickerSet, boolean cacheOnly) { return getStickerSet(inputStickerSet, null, cacheOnly, null); } @@ -3344,15 +3371,108 @@ public class MediaDataController extends BaseController { private int lastGuid; private TLRPC.User lastSearchUser; private TLRPC.Chat lastSearchChat; + private int messagesLocalSearchCount; private int[] messagesSearchCount = new int[]{0, 0}; private boolean[] messagesSearchEndReached = new boolean[]{false, false}; - private ArrayList searchResultMessages = new ArrayList<>(); - private SparseArray[] searchResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; + public ArrayList searchResultMessages = new ArrayList<>(); + public ArrayList searchServerResultMessages = new ArrayList<>(); + public ArrayList searchLocalResultMessages = new ArrayList<>(); + private SparseArray[] searchServerResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; + private ArrayList deletedFromResultMessages = new ArrayList<>(); private String lastSearchQuery; private int lastReturnedNum; private boolean loadingMoreSearchMessages; + private boolean loadingSearchLocal; + private boolean loadedPredirectedSearchLocal; - private int getMask() { + public void removeMessageFromResults(int id) { + for (int i = 0; i < searchResultMessages.size(); ++i) { + MessageObject m = searchResultMessages.get(i); + if (id == m.getId()) { + deletedFromResultMessages.add(searchResultMessages.remove(i)); + i--; + } + } + for (int i = 0; i < searchServerResultMessages.size(); ++i) { + MessageObject m = searchServerResultMessages.get(i); + if (id == m.getId()) { + searchServerResultMessages.remove(i); + i--; + } + } + for (int i = 0; i < searchLocalResultMessages.size(); ++i) { + MessageObject m = searchLocalResultMessages.get(i); + if (id == m.getId()) { + searchLocalResultMessages.remove(i); + i--; + } + } + } + + public boolean processDeletedMessage(int id, long[] topic_id) { + boolean updated = false; + MessageObject messageObject = null; + for (int i = 0; i < deletedFromResultMessages.size(); ++i) { + if (deletedFromResultMessages.get(i).getId() == id) { + messageObject = deletedFromResultMessages.get(i); + break; + } + } + if (messageObject != null && messageObject.getDialogId() == getUserConfig().getClientUserId()) { + updated = getMessagesController().processDeletedReactionTags(messageObject.messageOwner); + topic_id[0] = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), messageObject.messageOwner); + } + deletedFromResultMessages.remove(messageObject); + return updated; + } + + private void updateSearchResults() { + ArrayList previousSearchResultMessages = new ArrayList<>(searchResultMessages); + searchResultMessages.clear(); + HashSet messageIds = new HashSet<>(); + for (int i = 0; i < searchServerResultMessages.size(); ++i) { + MessageObject m = searchServerResultMessages.get(i); + if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) { + MessageObject prev = null; + for (int j = 0; j < previousSearchResultMessages.size(); ++j) { + if (previousSearchResultMessages.get(j).getId() == m.getId()) { + prev = previousSearchResultMessages.get(j); + break; + } + } + if (prev != null) { + m.copyStableParams(prev); + m.mediaExists = prev.mediaExists; + m.attachPathExists = prev.attachPathExists; + } + m.isSavedFiltered = true; + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + for (int i = 0; i < searchLocalResultMessages.size(); ++i) { + MessageObject m = searchLocalResultMessages.get(i); + if (!messageIds.contains(m.getId())) { + MessageObject prev = null; + for (int j = 0; j < previousSearchResultMessages.size(); ++j) { + if (previousSearchResultMessages.get(j).getId() == m.getId()) { + prev = previousSearchResultMessages.get(j); + break; + } + } + if (prev != null) { + m.copyStableParams(prev); + m.mediaExists = prev.mediaExists; + m.attachPathExists = prev.attachPathExists; + } + m.isSavedFiltered = true; + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + } + + public int getMask() { int mask = 0; if (lastReturnedNum < searchResultMessages.size() - 1 || !messagesSearchEndReached[0] || !messagesSearchEndReached[1]) { mask |= 1; @@ -3369,10 +3489,12 @@ public class MediaDataController extends BaseController { public void clearFoundMessageObjects() { searchResultMessages.clear(); + searchServerResultMessages.clear(); + searchLocalResultMessages.clear(); } public boolean isMessageFound(int messageId, boolean mergeDialog) { - return searchResultMessagesMap[mergeDialog ? 1 : 0].indexOfKey(messageId) >= 0; + return searchServerResultMessagesMap[mergeDialog ? 1 : 0].indexOfKey(messageId) >= 0; } public void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, TLRPC.User user, TLRPC.Chat chat, ReactionsLayoutInBubble.VisibleReaction reaction) { @@ -3385,29 +3507,52 @@ public class MediaDataController extends BaseController { } lastReturnedNum = index; MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], true); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), true); + } + + public int getSearchPosition() { + return lastReturnedNum; + } + + public int getSearchCount() { + if (searchServerResultMessages.isEmpty()) { + return Math.max(Math.max(messagesSearchCount[0] + messagesSearchCount[1], messagesLocalSearchCount), searchServerResultMessages.size()); + } + return Math.max(messagesSearchCount[0] + messagesSearchCount[1], searchServerResultMessages.size()); + } + + public void setSearchedPosition(int index) { + if (index < 0 || index >= searchResultMessages.size()) { + return; + } + lastReturnedNum = index; } public boolean searchEndReached() { - return messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]; + return messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1] || (loadingSearchLocal || loadedPredirectedSearchLocal); } - public void loadMoreSearchMessages() { - if (loadingMoreSearchMessages || messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]) { + public void loadMoreSearchMessages(boolean fromList) { + if (loadingMoreSearchMessages || reqId != 0 || messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]) { return; } - int temp = searchResultMessages.size(); + int temp = lastReturnedNum; lastReturnedNum = searchResultMessages.size(); + loadingMoreSearchMessages = true; searchMessagesInChat(null, lastDialogId, lastMergeDialogId, lastGuid, 1, lastReplyMessageId, false, lastSearchUser, lastSearchChat, false, lastReaction); lastReturnedNum = temp; - loadingMoreSearchMessages = true; } - private void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, boolean internal, TLRPC.User user, TLRPC.Chat chat, boolean jumpToMessage, ReactionsLayoutInBubble.VisibleReaction reaction) { + public boolean isSearchLoading() { + return reqId != 0; + } + + public void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, boolean internal, TLRPC.User user, TLRPC.Chat chat, boolean jumpToMessage, ReactionsLayoutInBubble.VisibleReaction reaction) { int max_id = 0; long queryWithDialog = dialogId; boolean firstQuery = !internal; if (reqId != 0) { + loadingMoreSearchMessages = false; getConnectionsManager().cancelRequest(reqId, true); reqId = 0; } @@ -3417,17 +3562,20 @@ public class MediaDataController extends BaseController { } if (query == null) { if (searchResultMessages.isEmpty()) { + loadingMoreSearchMessages = false; return; } if (direction == 1) { lastReturnedNum++; if (lastReturnedNum < searchResultMessages.size()) { MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + loadingMoreSearchMessages = false; return; } else { if (messagesSearchEndReached[0] && mergeDialogId == 0 && messagesSearchEndReached[1]) { lastReturnedNum--; + loadingMoreSearchMessages = false; return; } firstQuery = false; @@ -3454,17 +3602,20 @@ public class MediaDataController extends BaseController { lastReturnedNum = searchResultMessages.size() - 1; } MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + loadingMoreSearchMessages = false; return; } else { + loadingMoreSearchMessages = false; return; } } else if (firstQuery) { messagesSearchEndReached[0] = messagesSearchEndReached[1] = false; messagesSearchCount[0] = messagesSearchCount[1] = 0; searchResultMessages.clear(); - searchResultMessagesMap[0].clear(); - searchResultMessagesMap[1].clear(); + searchLocalResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); } if (messagesSearchEndReached[0] && !messagesSearchEndReached[1] && mergeDialogId != 0) { @@ -3527,6 +3678,7 @@ public class MediaDataController extends BaseController { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.peer = getMessagesController().getInputPeer(queryWithDialog); if (req.peer == null) { + loadingMoreSearchMessages = false; return; } lastGuid = guid; @@ -3545,6 +3697,33 @@ public class MediaDataController extends BaseController { req.from_id = MessagesController.getInputPeer(chat); req.flags |= 1; } + loadingSearchLocal = false; + loadedPredirectedSearchLocal = false; + int currentReqId = ++lastReqId; + final boolean isSaved = dialogId == getUserConfig().getClientUserId(); + if (isSaved && reaction != null && firstQuery) { + lastReturnedNum = 0; + searchServerResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); + + final int predictedCount = getMessagesController().getSavedTagCount(lastReplyMessageId, reaction); + messagesLocalSearchCount = TextUtils.isEmpty(req.q) ? predictedCount : 0; + loadingSearchLocal = true; + loadedPredirectedSearchLocal = false; + getMessagesStorage().searchSavedByTag(reaction.toTLReaction(), lastReplyMessageId, query, 300, searchLocalResultMessages == null ? 0 : searchLocalResultMessages.size(), (messages, users, chats, emojis) -> { + if (currentReqId == lastReqId) { + loadedPredirectedSearchLocal = messages.size() == predictedCount; + loadingSearchLocal = false; + getMessagesController().putUsers(users, true); + getMessagesController().putChats(chats, true); + AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).processDocuments(emojis); + searchLocalResultMessages = messages; + updateSearchResults(); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), dialogId, lastReturnedNum, getSearchCount(), true); + } + }, true); + } if (lastReplyMessageId != 0) { if (queryWithDialog == getUserConfig().getClientUserId()) { req.saved_peer_id = getMessagesController().getInputPeer(lastReplyMessageId); @@ -3559,7 +3738,6 @@ public class MediaDataController extends BaseController { req.flags |= 8; } req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); - int currentReqId = ++lastReqId; lastSearchQuery = query; long queryWithDialogFinal = queryWithDialog; String finalQuery = query; @@ -3568,10 +3746,13 @@ public class MediaDataController extends BaseController { if (error == null) { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; - int N = Math.min(res.messages.size(), 20); + int N = Math.min(res.messages.size(), req.limit - 1); for (int a = 0; a < N; a++) { TLRPC.Message message = res.messages.get(a); - MessageObject messageObject = new MessageObject(currentAccount, message, false, false); + MessageObject messageObject = new MessageObject(currentAccount, message, null, null, null, null, null, true, true, 0, false, false, isSaved); + if (messageObject.hasValidGroupId()) { + messageObject.isPrimaryGroupMessage = true; + } messageObject.setQuery(finalQuery); messageObjects.add(messageObject); } @@ -3594,38 +3775,47 @@ public class MediaDataController extends BaseController { getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); getMessagesController().putUsers(res.users, false); getMessagesController().putChats(res.chats, false); - if (req.offset_id == 0 && queryWithDialogFinal == dialogId) { - lastReturnedNum = 0; - searchResultMessages.clear(); - searchResultMessagesMap[0].clear(); - searchResultMessagesMap[1].clear(); - messagesSearchCount[0] = 0; - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); - } - boolean added = false; - int N = Math.min(res.messages.size(), 20); - for (int a = 0; a < N; a++) { - TLRPC.Message message = res.messages.get(a); - added = true; - MessageObject messageObject = messageObjects.get(a); - searchResultMessages.add(messageObject); - searchResultMessagesMap[queryWithDialogFinal == dialogId ? 0 : 1].put(messageObject.getId(), messageObject); - } - messagesSearchEndReached[queryWithDialogFinal == dialogId ? 0 : 1] = res.messages.size() < req.limit; - messagesSearchCount[queryWithDialogFinal == dialogId ? 0 : 1] = res instanceof TLRPC.TL_messages_messagesSlice || res instanceof TLRPC.TL_messages_channelMessages ? res.count : res.messages.size(); - if (searchResultMessages.isEmpty()) { - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0, jumpToMessage); - } else { - if (added) { - if (lastReturnedNum >= searchResultMessages.size()) { - lastReturnedNum = searchResultMessages.size() - 1; - } - MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); + Runnable done = () -> { + if (req.offset_id == 0 && queryWithDialogFinal == dialogId) { + lastReturnedNum = 0; + searchServerResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); + messagesSearchCount[0] = 0; + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); } - } - if (queryWithDialogFinal == dialogId && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) { - searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, chat, jumpToMessage, lastReaction); + boolean added = false; + int N = Math.min(res.messages.size(), req.limit - 1); + for (int a = 0; a < N; a++) { + added = true; + MessageObject messageObject = messageObjects.get(a); + searchServerResultMessages.add(messageObject); + searchServerResultMessagesMap[queryWithDialogFinal == dialogId ? 0 : 1].put(messageObject.getId(), messageObject); + } + updateSearchResults(); + messagesSearchEndReached[queryWithDialogFinal == dialogId ? 0 : 1] = res.messages.size() < req.limit; + messagesSearchCount[queryWithDialogFinal == dialogId ? 0 : 1] = res instanceof TLRPC.TL_messages_messagesSlice || res instanceof TLRPC.TL_messages_channelMessages ? res.count : res.messages.size(); + if (searchServerResultMessages.isEmpty()) { + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0, jumpToMessage); + } else { + if (added) { + if (lastReturnedNum >= searchResultMessages.size()) { + lastReturnedNum = searchResultMessages.size() - 1; + } + MessageObject messageObject = searchResultMessages.get(lastReturnedNum); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + } else if (isSaved) { + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), dialogId, lastReturnedNum, getSearchCount(), false); + } + } + if (queryWithDialogFinal == dialogId && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) { + searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, chat, jumpToMessage, lastReaction); + } + }; + if (isSaved) { + loadReplyMessagesForMessages(messageObjects, dialogId, false, lastReplyMessageId, done, guid); + } else { + done.run(); } } } @@ -3633,6 +3823,22 @@ public class MediaDataController extends BaseController { }, ConnectionsManager.RequestFlagFailOnServerErrors); } + public void portSavedSearchResults(int guid, ReactionsLayoutInBubble.VisibleReaction reaction, String query, ArrayList local, ArrayList loaded, int num, int count, boolean reached) { + lastReaction = reaction; + lastSearchQuery = query; + messagesSearchEndReached[0] = reached; + messagesSearchEndReached[1] = true; + searchServerResultMessages.clear(); + searchServerResultMessages.addAll(loaded); + searchLocalResultMessages.clear(); + searchLocalResultMessages.addAll(local); + updateSearchResults(); + messagesSearchCount[0] = count; + messagesSearchCount[1] = 0; + lastReturnedNum = num; + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), getUserConfig().getClientUserId(), lastReturnedNum, getSearchCount(), true); + } + public String getLastSearchQuery() { return lastSearchQuery; } @@ -3651,14 +3857,14 @@ public class MediaDataController extends BaseController { public final static int MEDIA_STORIES = 8; - public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex) { + public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex, ReactionsLayoutInBubble.VisibleReaction tag, String query) { boolean isChannel = DialogObject.isChatDialog(dialogId) && ChatObject.isChannel(-dialogId, currentAccount); if (BuildVars.LOGS_ENABLED) { FileLog.d("load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid); } - if (fromCache != 0 || DialogObject.isEncryptedDialog(dialogId)) { - loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, classGuid, isChannel, fromCache, requestIndex); + if (fromCache != 0 && TextUtils.isEmpty(query) || DialogObject.isEncryptedDialog(dialogId)) { + loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, tag, classGuid, isChannel, fromCache, requestIndex); } else { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.limit = count; @@ -3668,6 +3874,10 @@ public class MediaDataController extends BaseController { } else { req.offset_id = max_id; } + if (tag != null) { + req.flags |= 8; + req.saved_reaction.add(tag.toTLReaction()); + } if (type == MEDIA_PHOTOVIDEO) { req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); @@ -3686,7 +3896,11 @@ public class MediaDataController extends BaseController { } else if (type == MEDIA_GIF) { req.filter = new TLRPC.TL_inputMessagesFilterGif(); } - req.q = ""; + if (!TextUtils.isEmpty(query)) { + req.q = query; + } else { + req.q = ""; + } req.peer = getMessagesController().getInputPeer(dialogId); if (topicId != 0) { if (dialogId == getUserConfig().getClientUserId()) { @@ -3834,7 +4048,7 @@ public class MediaDataController extends BaseController { }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); } - if (!missing) { + if (!missing || getConnectionsManager().getConnectionState() != ConnectionsManager.ConnectionStateConnected) { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, countsFinal)); } } @@ -3864,7 +4078,7 @@ public class MediaDataController extends BaseController { } if (topicId != 0) { if (dialogId == getUserConfig().getClientUserId()) { - req.saved_peer_id = getMessagesController().getInputPeer(dialogId); + req.saved_peer_id = getMessagesController().getInputPeer(topicId); req.flags |= 4; } else { req.top_msg_id = (int) topicId; @@ -3967,7 +4181,7 @@ public class MediaDataController extends BaseController { if (fromCache == 2) { return; } - loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex); + loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex, null, null); } else { if (fromCache == 0) { ImageLoader.saveMessagesThumbs(res.messages); @@ -4093,11 +4307,12 @@ public class MediaDataController extends BaseController { }); } - private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, long topicId, int classGuid, boolean isChannel, int fromCache, int requestIndex) { + private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, long topicId, ReactionsLayoutInBubble.VisibleReaction tag, int classGuid, boolean isChannel, int fromCache, int requestIndex) { Runnable runnable = new Runnable() { @Override public void run() { boolean topReached = false; + final long selfId = getUserConfig().getClientUserId(); TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages(); try { ArrayList usersToLoad = new ArrayList<>(); @@ -4151,6 +4366,20 @@ public class MediaDataController extends BaseController { cursor.dispose(); } + String beforeWhere = ""; + String afterWhere = ""; + + if (tag != null) { + long taghash = 0; + if (!TextUtils.isEmpty(tag.emojicon)) { + taghash = tag.emojicon.hashCode(); + } else { + taghash = tag.documentId; + } + beforeWhere = "INNER JOIN tag_message_id t ON m.mid = t.mid"; + afterWhere = "t.tag = " + taghash + " AND"; + } + int holeMessageId = 0; if (max_id != 0) { int startHole = 0; @@ -4167,17 +4396,17 @@ public class MediaDataController extends BaseController { if (topicId != 0) { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid < %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, max_id, holeMessageId, type, countToLoad)); isEnd = false; } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid < %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, max_id, type, countToLoad)); } } else { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid < %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, max_id, holeMessageId, type, countToLoad)); isEnd = false; } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid < %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, max_id, type, countToLoad)); } } } else if (min_id != 0) { @@ -4195,17 +4424,17 @@ public class MediaDataController extends BaseController { reverseMessages = true; if (topicId != 0) { if (startHole > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, startHole, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid >= %d AND m.mid <= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, topicId, min_id, startHole, type, countToLoad)); } else { isEnd = true; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid >= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, topicId, min_id, type, countToLoad)); } } else { if (startHole > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, startHole, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid >= %d AND m.mid <= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, min_id, startHole, type, countToLoad)); } else { isEnd = true; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid >= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, min_id, type, countToLoad)); } } } else { @@ -4220,15 +4449,15 @@ public class MediaDataController extends BaseController { cursor.dispose(); if (topicId != 0) { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, type, countToLoad)); } } else { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, type, countToLoad)); } } } @@ -4254,17 +4483,21 @@ public class MediaDataController extends BaseController { } + HashSet groupsToLoad = tag != null ? new HashSet<>() : null; while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.readAttachPath(data, getUserConfig().clientUserId); + message.readAttachPath(data, selfId); data.reuse(); message.id = cursor.intValue(1); message.dialog_id = uid; if (DialogObject.isEncryptedDialog(uid)) { message.random_id = cursor.longValue(2); } + if (message.grouped_id != 0 && groupsToLoad != null) { + groupsToLoad.add(message.grouped_id); + } if (reverseMessages) { res.messages.add(0, message); } else { @@ -4276,6 +4509,38 @@ public class MediaDataController extends BaseController { } cursor.dispose(); + if (tag != null && !groupsToLoad.isEmpty()) { + for (long grouped_id : groupsToLoad) { + int index = -1; + for (int i = 0; i < res.messages.size(); ++i) { + if (res.messages.get(i).grouped_id == grouped_id) { + index = i; + break; + } + } + if (index < 0) continue; + cursor = database.queryFinalized("SELECT data, mid FROM messages_v2 WHERE uid = ? AND group_id = ? ORDER BY mid DESC", uid, grouped_id); + ArrayList groupMessages = new ArrayList<>(); + while (cursor.next()) { + int id = cursor.intValue(1); + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data == null) continue; + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.readAttachPath(data, selfId); + data.reuse(); + message.id = id; + message.dialog_id = uid; + groupMessages.add(message); + MessagesStorage.addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, null); + } + if (reverseMessages) + Collections.reverse(groupMessages); + res.messages.remove(index); + res.messages.addAll(index, groupMessages); + cursor.dispose(); + } + } + if (!usersToLoad.isEmpty()) { getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), res.users); } @@ -7566,8 +7831,12 @@ public class MediaDataController extends BaseController { } private HashMap currentFetchingEmoji = new HashMap<>(); + private HashSet fetchedEmoji = new HashSet<>(); public void fetchNewEmojiKeywords(String[] langCodes) { + fetchNewEmojiKeywords(langCodes, false); + } + public void fetchNewEmojiKeywords(String[] langCodes, boolean doNotFetchTwice) { if (langCodes == null) { return; } @@ -7576,7 +7845,7 @@ public class MediaDataController extends BaseController { if (TextUtils.isEmpty(langCode)) { return; } - if (currentFetchingEmoji.get(langCode) != null) { + if (currentFetchingEmoji.get(langCode) != null || doNotFetchTwice && fetchedEmoji.contains(langCode)) { return; } currentFetchingEmoji.put(langCode, true); @@ -7596,7 +7865,11 @@ public class MediaDataController extends BaseController { FileLog.e(e); } if (!BuildVars.DEBUG_VERSION && Math.abs(System.currentTimeMillis() - date) < 60 * 60 * 1000) { - AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); return; } TLObject request; @@ -7625,7 +7898,9 @@ public class MediaDataController extends BaseController { AndroidUtilities.runOnUIThread(() -> { currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); fetchNewEmojiKeywords(new String[]{langCode}); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); }); } catch (Exception e) { FileLog.e(e); @@ -7633,9 +7908,16 @@ public class MediaDataController extends BaseController { }); } else { putEmojiKeywords(langCode, res); + AndroidUtilities.runOnUIThread(() -> { + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); } } else { - AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); } }); }); @@ -7752,6 +8034,44 @@ public class MediaDataController extends BaseController { }); } + public void getEmojiNames(String[] langCodes, String emoji, Utilities.Callback> whenDone) { + if (whenDone == null || emoji == null) return; + getMessagesStorage().getStorageQueue().postRunnable(() -> { + SQLiteCursor cursor = null; + try { + Object[] args = new Object[1 + langCodes.length]; + args[0] = emoji; + String langQuery = "1 = 1"; + for (int i = 0; i < langCodes.length; ++i) { + if (i == 0) langQuery = "lang = ?"; + else langQuery = langQuery + " OR lang = ?"; + cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT alias FROM emoji_keywords_info_v2 WHERE lang = ?", langCodes[i]); + if (cursor.next()) { + langCodes[i] = cursor.stringValue(0); + } + cursor.dispose(); + args[1 + i] = langCodes[i]; + } + cursor = getMessagesStorage().getDatabase().executeFast("SELECT keyword FROM emoji_keywords_v2 WHERE emoji = ? AND (" + langQuery + ")").query(args); + ArrayList names = new ArrayList<>(); + while (cursor.next()) { + String name = cursor.stringValue(0); + names.add(name); + } + AndroidUtilities.runOnUIThread(() -> { + whenDone.run(names); + }); + } catch (Exception e) { + FileLog.e(e); + } finally { + if (cursor != null) { + cursor.dispose(); + cursor = null; + } + } + }); + } + public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, boolean allowAnimated) { getEmojiSuggestions(langCodes, keyword, fullMatch, callback, null, allowAnimated, false, false, null); } @@ -8502,7 +8822,7 @@ public class MediaDataController extends BaseController { saveReactionsToPref(savedReactionsPref, reactions.hash, reactions.reactions); - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L); } if (response instanceof TLRPC.TL_messages_reactionsNotModified) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index b84d23fc1..0559a9c46 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -34,6 +34,7 @@ import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.Base64; import android.util.Log; +import android.util.SparseIntArray; import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; @@ -167,6 +168,7 @@ public class MessageObject { public long eventId; public int contentType; public String dateKey; + public int dateKeyInt; public String monthKey; public boolean deleted; public boolean deletedByThanos; @@ -315,6 +317,7 @@ public class MessageObject { public boolean forceAvatar; public Drawable customAvatarDrawable; public boolean isSaved; + public boolean isSavedFiltered; private byte[] randomWaveform; public boolean drawServiceWithDefaultTypeface; @@ -567,6 +570,10 @@ public class MessageObject { return !(replyMessageObject != null && replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty) && messageOwner.reply_to != null && messageOwner.reply_to.story_id != 0 && (messageOwner.flags & TLRPC.MESSAGE_FLAG_REPLY) != 0; } + public boolean isUnsupported() { + return getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported; + } + public boolean isExpiredStory() { return (type == MessageObject.TYPE_STORY || type == MessageObject.TYPE_STORY_MENTION) && messageOwner.media.storyItem instanceof TL_stories.TL_storyItemDeleted; } @@ -926,9 +933,21 @@ public class MessageObject { public ArrayList messages = new ArrayList<>(); public ArrayList posArray = new ArrayList<>(); public HashMap positions = new HashMap<>(); + public LongSparseArray positionsArray = new LongSparseArray<>(); public MessageObject captionMessage; public boolean isDocuments; + public GroupedMessagePosition getPosition(MessageObject msg) { + if (msg == null) { + return null; + } + GroupedMessagePosition pos = positions.get(msg); + if (pos == null) { + pos = positionsArray.get(msg.getId()); + } + return pos; + } + private int maxSizeWidth = 800; public final TransitionParams transitionParams = new TransitionParams(); @@ -967,6 +986,7 @@ public class MessageObject { public void calculate() { posArray.clear(); positions.clear(); + positionsArray.clear(); captionMessage = null; maxSizeWidth = 800; @@ -996,6 +1016,7 @@ public class MessageObject { for (int a = (reversed ? count - 1 : 0); (reversed ? a >= 0 : a < count);) { MessageObject messageObject = messages.get(a); if (a == (reversed ? count - 1 : 0)) { + messageObject.isOutOwnerCached = null; isOut = messageObject.isOutOwner(); needShare = !isOut && ( messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.saved_from_peer != null || @@ -1026,6 +1047,7 @@ public class MessageObject { } positions.put(messageObject, position); + positionsArray.put(messageObject.getId(), position); posArray.add(position); if (messageObject.caption != null) { @@ -1048,19 +1070,21 @@ public class MessageObject { for (int a = 0; a < count; a++) { GroupedMessagePosition pos = posArray.get(a); pos.flags = POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT; - if (!reversed && a == 0 || reversed && a == count - 1) { + if (a == 0) { pos.flags |= POSITION_FLAG_TOP; pos.last = false; - } else if (reversed && a == 0 || !reversed && a == count - 1) { + } else if (a == count - 1) { pos.flags |= POSITION_FLAG_BOTTOM; pos.last = true; + } else { + pos.last = false; } pos.edge = true; pos.aspectRatio = 1.0f; pos.minX = 0; pos.maxX = 0; - pos.minY = (byte) (reversed ? count - 1 - a : a); - pos.maxY = (byte) (reversed ? count - 1 - a : a); + pos.minY = (byte) a; + pos.maxY = (byte) a; pos.spanSize = 1000; pos.pw = maxSizeWidth; pos.ph = 100; @@ -1366,7 +1390,7 @@ public class MessageObject { } public MessageObject findPrimaryMessageObject() { - return findMessageWithFlags(MessageObject.POSITION_FLAG_TOP | MessageObject.POSITION_FLAG_LEFT); + return findMessageWithFlags(reversed ? MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_RIGHT : MessageObject.POSITION_FLAG_TOP | MessageObject.POSITION_FLAG_LEFT); } public MessageObject findCaptionMessageObject() { @@ -1535,7 +1559,7 @@ public class MessageObject { this.isRepostPreview = isRepostPreview; this.isRepostVideoPreview = isRepostVideoPreview; - this.isSaved = isSavedMessages; + this.isSaved = isSavedMessages || getDialogId(message) == UserConfig.getInstance(accountNum).getClientUserId(); currentAccount = accountNum; messageOwner = message; @@ -1565,6 +1589,7 @@ public class MessageObject { int dateYear = rightNow.get(Calendar.YEAR); int dateMonth = rightNow.get(Calendar.MONTH); dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay); + dateKeyInt = dateYear + 10000 * dateMonth + 10000 * 100 * dateDay; monthKey = String.format("%d_%02d", dateYear, dateMonth); createMessageSendInfo(); @@ -1809,6 +1834,7 @@ public class MessageObject { int dateYear = rightNow.get(Calendar.YEAR); int dateMonth = rightNow.get(Calendar.MONTH); dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay); + dateKeyInt = dateYear + 1000 * dateMonth + 1000 * 100 * dateDay; monthKey = String.format("%d_%02d", dateYear, dateMonth); TLRPC.Peer peer_id = new TLRPC.TL_peerChannel(); @@ -2611,19 +2637,31 @@ public class MessageObject { messageText = replaceWithLink(LocaleController.getString("EventLogSendMessages", R.string.EventLogSendMessages), "un1", fromUser); } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions) { TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions eventActionChangeAvailableReactions = (TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions) event.action; - - CharSequence oldReactions = getStringFrom(eventActionChangeAvailableReactions.prev_value); + boolean customReactionsChanged = eventActionChangeAvailableReactions.prev_value instanceof TLRPC.TL_chatReactionsSome + && eventActionChangeAvailableReactions.new_value instanceof TLRPC.TL_chatReactionsSome; CharSequence newReactions = getStringFrom(eventActionChangeAvailableReactions.new_value); - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChanged", R.string.ActionReactionsChanged, "**old**", "**new**"), "un1", fromUser)); - int i = spannableStringBuilder.toString().indexOf("**old**"); - if (i > 0) { - spannableStringBuilder.replace(i, i + "**old**".length(), oldReactions); + String newStr = "**new**"; + String oldStr = "**old**"; + if (customReactionsChanged) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChangedList", R.string.ActionReactionsChangedList, newStr), "un1", fromUser)); + int i = spannableStringBuilder.toString().indexOf(newStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + newStr.length(), newReactions); + } + messageText = spannableStringBuilder; + } else { + CharSequence oldReactions = getStringFrom(eventActionChangeAvailableReactions.prev_value); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChanged", R.string.ActionReactionsChanged, oldStr, newStr), "un1", fromUser)); + int i = spannableStringBuilder.toString().indexOf(oldStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + oldStr.length(), oldReactions); + } + i = spannableStringBuilder.toString().indexOf(newStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + newStr.length(), newReactions); + } + messageText = spannableStringBuilder; } - i = spannableStringBuilder.toString().indexOf("**new**"); - if (i > 0) { - spannableStringBuilder.replace(i, i + "**new**".length(), newReactions); - } - messageText = spannableStringBuilder; } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeUsernames) { TLRPC.TL_channelAdminLogEventActionChangeUsernames log = (TLRPC.TL_channelAdminLogEventActionChangeUsernames) event.action; @@ -3030,10 +3068,12 @@ public class MessageObject { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); for (int i = 0; i < reactionsSome.reactions.size(); i++) { if (i != 0) { - spannableStringBuilder.append(", "); + spannableStringBuilder.append(" "); } - spannableStringBuilder.append(ReactionsUtils.reactionToCharSequence(reactionsSome.reactions.get(i))); + CharSequence reaction = ReactionsUtils.reactionToCharSequence(reactionsSome.reactions.get(i)); + spannableStringBuilder.append(Emoji.replaceEmoji(reaction, null, false)); } + return spannableStringBuilder; } return LocaleController.getString("NoReactions", R.string.NoReactions); } @@ -3334,6 +3374,18 @@ public class MessageObject { return messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty(); } + public boolean hasReaction(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (!hasReactions() || reaction == null) return false; + for (int i = 0; i < messageOwner.reactions.results.size(); ++i) { + TLRPC.ReactionCount rc = messageOwner.reactions.results.get(i); + if (reaction.isSame(rc.reaction)) { + return true; + } + } + return false; + } + + public static void updatePollResults(TLRPC.TL_messageMediaPoll media, TLRPC.PollResults results) { if (media == null || results == null) { return; @@ -4554,7 +4606,7 @@ public class MessageObject { } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice) { messageText = getMedia(messageOwner).description; } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) { - messageText = LocaleController.getString(ApplicationLoader.applicationLoaderInstance.isStandalone() ? R.string.UnsupportedMediaStandalone : R.string.UnsupportedMedia); + messageText = LocaleController.getString(R.string.UnsupportedMedia2); } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) { if (isSticker() || isAnimatedStickerDocument(getDocument(), true)) { String sch = getStickerChar(); @@ -4666,7 +4718,7 @@ public class MessageObject { } else if (media instanceof TLRPC.TL_messageMediaInvoice) { return media.description; } else if (media instanceof TLRPC.TL_messageMediaUnsupported) { - return LocaleController.getString(ApplicationLoader.applicationLoaderInstance.isStandalone() ? R.string.UnsupportedMediaStandalone : R.string.UnsupportedMedia); + return LocaleController.getString(R.string.UnsupportedMedia2); } else if (media instanceof TLRPC.TL_messageMediaDocument) { if (isStickerDocument(media.document) || isAnimatedStickerDocument(media.document, true)) { String sch = getStickerChar(); @@ -5770,6 +5822,8 @@ public class MessageObject { return result; } + // only set in searching with tags + public boolean isPrimaryGroupMessage; public boolean hasValidGroupId() { return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || isMusic() || isDocument()); } @@ -5823,7 +5877,7 @@ public class MessageObject { if (text == null) { return false; } - if (isRestrictedMessage) { + if (isRestrictedMessage || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) { ArrayList entities = new ArrayList<>(); TLRPC.TL_messageEntityItalic entityItalic = new TLRPC.TL_messageEntityItalic(); entityItalic.offset = 0; @@ -6282,8 +6336,8 @@ public class MessageObject { if (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage) { maxWidth -= dp(52); } - if (needDrawShareButton() && !isOutOwner()) { - maxWidth -= dp(10); + if (needDrawShareButton() && (isSaved || !isOutOwner())) { + maxWidth -= dp(isSaved && isOutOwner() ? 40 : 10); } if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) { maxWidth -= dp(10); @@ -6328,17 +6382,18 @@ public class MessageObject { } boolean useManualParse = !hasEntities && ( - eventId != 0 || - messageOwner instanceof TLRPC.TL_message_old || - messageOwner instanceof TLRPC.TL_message_old2 || - messageOwner instanceof TLRPC.TL_message_old3 || - messageOwner instanceof TLRPC.TL_message_old4 || - messageOwner instanceof TLRPC.TL_messageForwarded_old || - messageOwner instanceof TLRPC.TL_messageForwarded_old2 || - messageOwner instanceof TLRPC.TL_message_secret || - getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice || - isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || - messageOwner.id < 0 || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported); + eventId != 0 || + messageOwner instanceof TLRPC.TL_message_old || + messageOwner instanceof TLRPC.TL_message_old2 || + messageOwner instanceof TLRPC.TL_message_old3 || + messageOwner instanceof TLRPC.TL_message_old4 || + messageOwner instanceof TLRPC.TL_messageForwarded_old || + messageOwner instanceof TLRPC.TL_messageForwarded_old2 || + messageOwner instanceof TLRPC.TL_message_secret || + getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice || + isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || + messageOwner.id < 0 + ); if (useManualParse) { addLinks(isOutOwner(), messageText, true, true); @@ -7239,7 +7294,7 @@ public class MessageObject { return isOutOwnerCached; } long selfUserId = UserConfig.getInstance(currentAccount).getClientUserId(); - if (isSaved && messageOwner.fwd_from != null) { + if ((isSaved || getDialogId() == selfUserId) && messageOwner.fwd_from != null) { return isOutOwnerCached = messageOwner.fwd_from.from_id != null && messageOwner.fwd_from.from_id.user_id == selfUserId || messageOwner.fwd_from.saved_out; } TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null; @@ -7261,7 +7316,7 @@ public class MessageObject { return true; } if (isSaved) { - return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS; + return true; } if (forceAvatar || customAvatarDrawable != null) { return true; @@ -7274,7 +7329,7 @@ public class MessageObject { return true; } if (isSaved) { - return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS; + return true; } if (forceAvatar || customAvatarDrawable != null) { return true; @@ -8777,6 +8832,9 @@ public class MessageObject { } public boolean needDrawForwarded() { + if (type == MessageObject.TYPE_STORY && !isExpiredStory()) { + return true; + } if (isSaved) { if (messageOwner == null || messageOwner.fwd_from == null) return false; final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); @@ -8788,9 +8846,6 @@ public class MessageObject { if (fromId == 0) return savedId != UserObject.ANONYMOUS; return savedId != fromId && fromId != selfId; } - if (type == MessageObject.TYPE_STORY && !isExpiredStory()) { - return true; - } return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0 && messageOwner.fwd_from != null && !messageOwner.fwd_from.imported && (messageOwner.fwd_from.saved_from_peer == null || !(messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) || messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id) && UserConfig.getInstance(currentAccount).getClientUserId() != getDialogId(); } @@ -9341,7 +9396,7 @@ public class MessageObject { } else { text = messageText; } - CharSequence charSequence = AndroidUtilities.replaceCharSequence("\n", text, " "); + CharSequence charSequence = AndroidUtilities.replaceMultipleCharSequence("\n", text, " "); if (inQuote && messageOwner != null && messageOwner.reply_to != null && messageOwner.reply_to.quote_text != null) { SpannableStringBuilder quoteText = new SpannableStringBuilder(messageOwner.reply_to.quote_text); addEntitiesToText(quoteText, messageOwner.reply_to.quote_entities, isOutOwner(), false, false, false); @@ -9354,13 +9409,13 @@ public class MessageObject { String str = charSequence.toString(); int lastIndex = str.length(); int startHighlightedIndex = str.toLowerCase().indexOf(foundWords.get(0)); - int maxSymbols = 200; + int maxSymbols = 120; if (startHighlightedIndex < 0) { startHighlightedIndex = 0; } if (lastIndex > maxSymbols) { - int newStart = Math.max(0, startHighlightedIndex - maxSymbols / 2); - charSequence = charSequence.subSequence(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + maxSymbols / 2)); + int newStart = Math.max(0, startHighlightedIndex - (int) (maxSymbols * .1f)); + charSequence = charSequence.subSequence(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + (int) (maxSymbols * .9f))); } messageTrimmedToHighlight = charSequence; } @@ -9462,9 +9517,6 @@ public class MessageObject { if (newReaction.count <= 0) { messageOwner.reactions.results.remove(newReaction); } - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(visibleReaction, false); - } } if (messageOwner.reactions.can_see_list) { for (int i = 0; i < messageOwner.reactions.recent_reactions.size(); i++) { @@ -9491,9 +9543,6 @@ public class MessageObject { if (choosenReaction.count <= 0) { messageOwner.reactions.results.remove(choosenReaction); } - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(choosenReaction.reaction), false); - } choosenReactions.remove(choosenReaction); if (messageOwner.reactions.can_see_list) { @@ -9514,9 +9563,6 @@ public class MessageObject { newReaction.chosen = true; newReaction.count++; newReaction.chosen_order = maxChoosenOrder + 1; - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(visibleReaction, true); - } if (messageOwner.reactions.can_see_list || (messageOwner.dialog_id > 0 && maxReactionsCount > 1)) { TLRPC.TL_messagePeerReaction action = new TLRPC.TL_messagePeerReaction(); @@ -9791,13 +9837,14 @@ public class MessageObject { webpage != null && (webpage.photo != null || isVideoDocument(webpage.document)) && !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && !(isSponsored() && sponsoredWebPage == null && sponsoredChannelPost == 0) && // drawInstantViewType = 1 - !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 - !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 - !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 - !"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11 - !"telegram_user".equals(webpageType) && // drawInstantViewType = 13 - !"telegram_story".equals(webpageType) && // drawInstantViewType = 17 - !"telegram_channel_boost".equals(webpageType) // drawInstantViewType = 18 + !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 + !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 + !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 + !"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11 + !"telegram_user".equals(webpageType) && // drawInstantViewType = 13 + !"telegram_story".equals(webpageType) && // drawInstantViewType = 17 + !"telegram_channel_boost".equals(webpageType) && // drawInstantViewType = 18 + !"telegram_chat".equals(webpageType) ; } @@ -9805,11 +9852,14 @@ public class MessageObject { final boolean hasLinkPreview = !isRestrictedMessage && MessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && MessageObject.getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage; final TLRPC.WebPage webpage = hasLinkPreview ? MessageObject.getMedia(messageOwner).webpage : null; final String webpageType = webpage != null ? webpage.type : null; - return !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && ("app".equals(webpageType) || "profile".equals(webpageType) || + return !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && ( + "app".equals(webpageType) || "profile".equals(webpageType) || "article".equals(webpageType) || "telegram_bot".equals(webpageType) || "telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) || "telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) || - "telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType)); + "telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) || + "telegram_chat".equals(webpageType) + ); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 03faf00fe..1421c7ff5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -584,6 +584,9 @@ public class MessagesController extends BaseController implements NotificationCe public int savedDialogsPinnedLimitDefault; public int savedDialogsPinnedLimitPremium; + public boolean savedViewAsChats; + public boolean storyQualityFull; + public int uploadMaxFileParts; public int uploadMaxFilePartsPremium; @@ -1472,6 +1475,8 @@ public class MessagesController extends BaseController implements NotificationCe boostsChannelLevelMax = mainPreferences.getInt("boostsChannelLevelMax", 100); savedDialogsPinnedLimitDefault = mainPreferences.getInt("savedDialogsPinnedLimitDefault", 4); savedDialogsPinnedLimitPremium = mainPreferences.getInt("savedDialogsPinnedLimitPremium", 6); + storyQualityFull = mainPreferences.getBoolean("storyQualityFull", true); + savedViewAsChats = mainPreferences.getBoolean("savedViewAsChats", false); scheduleTranscriptionUpdate(); BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID); if (mainPreferences.contains("dcDomainName2")) { @@ -4919,6 +4924,9 @@ public class MessagesController extends BaseController implements NotificationCe } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { loadAppConfig(false); getContactsController().reloadContactsStatusesMaybe(true); + if (storyQualityFull && !getUserConfig().isPremium() || getUserConfig().isPremium()) { + getNotificationCenter().postNotificationName(NotificationCenter.storyQualityUpdate); + } } } @@ -7906,6 +7914,9 @@ public class MessagesController extends BaseController implements NotificationCe protected void deleteDialog(long did, int first, int onlyHistory, int max_id, boolean revoke, TLRPC.InputPeer peer, long taskId) { if (onlyHistory == 2) { + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } getMessagesStorage().deleteDialog(did, onlyHistory); return; } @@ -7930,6 +7941,9 @@ public class MessagesController extends BaseController implements NotificationCe if (first == 1 && max_id == 0) { TLRPC.InputPeer peerFinal = peer; getMessagesStorage().getDialogMaxMessageId(did, (param) -> { + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } deleteDialog(did, 2, onlyHistory, Math.max(0, param), revoke, peerFinal, taskId); checkIfFolderEmpty(1); }); @@ -7945,6 +7959,9 @@ public class MessagesController extends BaseController implements NotificationCe FileLog.d("delete dialog with id " + did); } boolean isPromoDialog = false; + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } getMessagesStorage().deleteDialog(did, onlyHistory); TLRPC.Dialog dialog = dialogs_dict.get(did); if (onlyHistory == 0 || onlyHistory == 3) { @@ -17284,6 +17301,8 @@ public class MessagesController extends BaseController implements NotificationCe getMediaDataController().loadRecentAndTopReactions(true); } else if (baseUpdate instanceof TLRPC.TL_updateRecentReactions) { getMediaDataController().loadSavedReactions(true); + } else if (baseUpdate instanceof TLRPC.TL_updateSavedReactionTags) { + getSavedReactionTags(0, true); } else if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) { getMediaDataController().loadRecents(MediaDataController.TYPE_FAVE, false, false, true); } else if (baseUpdate instanceof TLRPC.TL_updateContactsReset) { @@ -19960,24 +19979,56 @@ public class MessagesController extends BaseController implements NotificationCe return rec; } - private boolean loadedReactionTags; - private TLRPC.TL_messages_savedReactionsTags reactionTags; - public void updateSavedReactionTags(ReactionsLayoutInBubble.VisibleReaction reaction, boolean add) { - if (reactionTags != null) { + private HashSet loadingReactionTags; + private LongSparseArray reactionTags; + + public boolean processDeletedReactionTags(TLRPC.Message message) { + if (message == null || DialogObject.getPeerDialogId(message.peer_id) != getUserConfig().getClientUserId() || message.reactions == null || !message.reactions.reactions_as_tags || message.reactions.results == null) { + return false; + } + long topic_id = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), message); + boolean changed = false; + for (int i = 0; i < message.reactions.results.size(); ++i) { + if (updateSavedReactionTags(topic_id, ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.reactions.results.get(i).reaction), false, false)) { + changed = true; + } + } + return changed; + } + + public boolean updateSavedReactionTags(long topic_id, ReactionsLayoutInBubble.VisibleReaction reaction, boolean add, boolean update) { + if (reactionTags == null) { + return false; + } + boolean gchanged = false; + for (int a = 0; a < 2; ++a) { + long topicId = a == 0 ? 0 : topic_id; + if (a == 1 && topicId == 0) continue; + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topicId); + if (tags == null) { + if (topicId != 0) { + reactionTags.put(topicId, tags = new TLRPC.TL_messages_savedReactionsTags()); + } else { + continue; + } + } boolean changed = false; boolean found = false; - for (int i = 0; i < reactionTags.tags.size(); ++i) { - TLRPC.TL_savedReactionTag tag = reactionTags.tags.get(i); + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); if (reaction.isSame(tag.reaction)) { found = true; int wasCount = tag.count; tag.count = Math.max(0, tag.count + (add ? +1 : -1)); if (tag.count <= 0) { - reactionTags.tags.remove(i); + tags.tags.remove(i); i--; + changed = true; + gchanged = true; } else if (tag.count != wasCount) { changed = true; + gchanged = true; } } } @@ -19985,43 +20036,205 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.TL_savedReactionTag tag = new TLRPC.TL_savedReactionTag(); tag.reaction = reaction.toTLReaction(); tag.count = 1; - reactionTags.tags.add(tag); + tags.tags.add(tag); changed = true; + gchanged = true; } - if (changed) { - Collections.sort(reactionTags.tags, (a, b) -> b.count - a.count); - long hash = 0; - for (int i = 0; i < reactionTags.tags.size(); ++i) { - TLRPC.TL_savedReactionTag tag = reactionTags.tags.get(i); - if (tag.count <= 0) continue; - if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { - String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); - hash = MediaDataController.calcHash(hash, Long.parseLong(md5.substring(0, 16), 16)); - } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { - hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); - } - if ((tag.flags & 1) != 0 && tag.title != null) { - hash = MediaDataController.calcHash(hash, Long.parseLong(Utilities.MD5(tag.title).substring(0, 16), 16)); - } - hash = MediaDataController.calcHash(hash, tag.count); - } - reactionTags.hash = hash; - saveSavedReactionsTags(reactionTags); - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + if (update && changed) { + updateSavedReactionTags(topicId); } } + return gchanged; + } + + public void updateSavedReactionTags(HashSet topic_ids) { + updateSavedReactionTags(0); + for (long topic_id : topic_ids) { + updateSavedReactionTags(topic_id); + } } - public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags() { - if (loadedReactionTags) { - return reactionTags; + + public void updateSavedReactionTags(long topic_id) { + if (reactionTags == null) return; + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topic_id); + if (tags == null) { + if (topic_id != 0) { + reactionTags.put(topic_id, tags = new TLRPC.TL_messages_savedReactionsTags()); + } else { + return; + } } - loadedReactionTags = true; + Collections.sort(tags.tags, (a, b) -> { + if (a.count == b.count) { + return Long.compareUnsigned(getTagLongId(b.reaction), getTagLongId(a.reaction)); + } + return b.count - a.count; + }); + long hash = 0; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (tag.count <= 0) continue; + if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(md5.substring(0, 16), 16)); + } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); + } + if (topic_id == 0 && (tag.flags & 1) != 0 && tag.title != null) { + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(Utilities.MD5(tag.title).substring(0, 16), 16)); + } + hash = MediaDataController.calcHash(hash, tag.count); + } + tags.hash = hash; + saveSavedReactionsTags(topic_id, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + } + + public String getSavedTagName(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (reactionTags == null) { + return null; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) return null; + for (int i = 0; i < tags.tags.size(); ++i) { + if (reaction.isSame(tags.tags.get(i).reaction)) { + return tags.tags.get(i).title; + } + } + return null; + } + + public int getSavedTagCount(long topic_id, ReactionsLayoutInBubble.VisibleReaction reaction) { + if (reactionTags == null) { + return 0; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topic_id); + if (tags == null) return 0; + for (int i = 0; i < tags.tags.size(); ++i) { + if (reaction.isSame(tags.tags.get(i).reaction)) { + return tags.tags.get(i).count; + } + } + return 0; + } + + public String getSavedTagName(TLRPC.Reaction reaction) { + if (reactionTags == null) { + return null; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) return null; + for (int i = 0; i < tags.tags.size(); ++i) { + if (ReactionsLayoutInBubble.reactionsEqual(reaction, tags.tags.get(i).reaction)) { + return tags.tags.get(i).title; + } + } + return null; + } + + public void renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction reaction, String name) { + if (reactionTags == null) { + return; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) { + reactionTags.put(0, tags = new TLRPC.TL_messages_savedReactionsTags()); + } + boolean found = false; + boolean changed = false; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (reaction.isSame(tag.reaction)) { + found = true; + if (TextUtils.isEmpty(name)) { + changed = tag.title != null; + tag.flags &=~ 1; + tag.title = null; + } else { + changed = !TextUtils.equals(tag.title, name); + tag.flags |= 1; + tag.title = name; + } + break; + } + } + if (!found) { + TLRPC.TL_savedReactionTag tag = new TLRPC.TL_savedReactionTag(); + tag.reaction = reaction.toTLReaction(); + if (!TextUtils.isEmpty(name)) { + tag.title = name; + } + tag.count = 1; + tags.tags.add(tag); + changed = true; + } + if (changed) { + TLRPC.TL_messages_updateSavedReactionTag req = new TLRPC.TL_messages_updateSavedReactionTag(); + req.reaction = reaction.toTLReaction(); + if (!TextUtils.isEmpty(name)) { + req.flags |= 1; + req.title = name; + } + getConnectionsManager().sendRequest(req, null); + + Collections.sort(tags.tags, (a, b) -> { + if (a.count == b.count) { + return Long.compareUnsigned(getTagLongId(b.reaction), getTagLongId(a.reaction)); + } + return b.count - a.count; + }); + long hash = 0; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (tag.count <= 0) continue; + if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(md5.substring(0, 16), 16)); + } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); + } + if ((tag.flags & 1) != 0 && tag.title != null) { + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(Utilities.MD5(tag.title).substring(0, 16), 16)); + } + hash = MediaDataController.calcHash(hash, tag.count); + } + tags.hash = hash; + saveSavedReactionsTags(0, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L); + } + } + + private long getTagLongId(TLRPC.Reaction reaction) { + if (reaction == null) return 0; + if (reaction.tag_long_id != 0) return reaction.tag_long_id; + if (reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) reaction).emoticon); + return reaction.tag_long_id = Long.parseUnsignedLong(md5.substring(0, 16), 16); + } else if (reaction instanceof TLRPC.TL_reactionCustomEmoji) { + return reaction.tag_long_id = ((TLRPC.TL_reactionCustomEmoji) reaction).document_id; + } + return 0; + } + + public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags(long topic_id) { + return getSavedReactionTags(topic_id, false); + } + + public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags(long topic_id, boolean force) { + if (loadingReactionTags != null && loadingReactionTags.contains(topic_id) && !force) { + if (reactionTags == null) return null; + return reactionTags.get(topic_id); + } + if (loadingReactionTags == null) { + loadingReactionTags = new HashSet<>(); + } + loadingReactionTags.add(topic_id); getMessagesStorage().getStorageQueue().postRunnable(() -> { TLRPC.messages_SavedReactionTags result = null; SQLiteDatabase database = getMessagesStorage().getDatabase(); SQLiteCursor cursor = null; try { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM saved_reaction_tags")); + cursor = database.queryFinalized("SELECT data FROM saved_reaction_tags WHERE topic_id = ?", topic_id); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -20039,20 +20252,31 @@ public class MessagesController extends BaseController implements NotificationCe final TLRPC.messages_SavedReactionTags finalResult = result; AndroidUtilities.runOnUIThread(() -> { + if (reactionTags == null) reactionTags = new LongSparseArray<>(); if (finalResult instanceof TLRPC.TL_messages_savedReactionsTags) { - reactionTags = (TLRPC.TL_messages_savedReactionsTags) finalResult; - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + reactionTags.put(topic_id, (TLRPC.TL_messages_savedReactionsTags) finalResult); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); } TLRPC.TL_messages_getSavedReactionTags req = new TLRPC.TL_messages_getSavedReactionTags(); if (finalResult instanceof TLRPC.TL_messages_savedReactionsTags) { req.hash = finalResult.hash; } + if (topic_id != 0) { + req.flags |= 1; + req.peer = getInputPeer(topic_id); + } getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.TL_messages_savedReactionsTags) { - reactionTags = (TLRPC.TL_messages_savedReactionsTags) res; - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); - saveSavedReactionsTags(reactionTags); + TLRPC.TL_messages_savedReactionsTags tags = (TLRPC.TL_messages_savedReactionsTags) res; + reactionTags.put(topic_id, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + saveSavedReactionsTags(topic_id, tags); + } else if (res instanceof TLRPC.TL_messages_savedReactionsTagsNotModified && finalResult == null && req.hash == 0) { + TLRPC.TL_messages_savedReactionsTags emptyTags = new TLRPC.TL_messages_savedReactionsTags(); + reactionTags.put(topic_id, emptyTags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + saveSavedReactionsTags(topic_id, emptyTags); } })); }); @@ -20060,17 +20284,18 @@ public class MessagesController extends BaseController implements NotificationCe return null; } - private void saveSavedReactionsTags(TLRPC.TL_messages_savedReactionsTags res) { + private void saveSavedReactionsTags(long topic_id, TLRPC.TL_messages_savedReactionsTags res) { getMessagesStorage().getStorageQueue().postRunnable(() -> { SQLiteDatabase database2 = getMessagesStorage().getDatabase(); SQLitePreparedStatement state = null; try { - database2.executeFast("DELETE FROM saved_reaction_tags WHERE 1").stepThis().dispose(); - state = database2.executeFast("REPLACE INTO saved_reaction_tags VALUES(?)"); + database2.executeFast("DELETE FROM saved_reaction_tags WHERE topic_id = " + topic_id).stepThis().dispose(); + state = database2.executeFast("REPLACE INTO saved_reaction_tags VALUES(?, ?)"); state.requery(); NativeByteBuffer buffer = new NativeByteBuffer(res.getObjectSize()); res.serializeToStream(buffer); - state.bindByteBuffer(1, buffer); + state.bindLong(1, topic_id); + state.bindByteBuffer(2, buffer); state.step(); } catch (Exception e) { FileLog.e(e); @@ -20116,6 +20341,27 @@ public class MessagesController extends BaseController implements NotificationCe } } + public void setStoryQuality(boolean full) { + if (storyQualityFull != full) { + mainPreferences.edit().putBoolean("storyQualityFull", storyQualityFull = full).apply(); + getNotificationCenter().postNotificationName(NotificationCenter.storyQualityUpdate); + } + } + + public void setSavedViewAs(boolean chats) { + if (savedViewAsChats != chats) { + mainPreferences.edit().putBoolean("savedViewAsChats", savedViewAsChats = chats).apply(); + } + } + + public boolean isStoryQualityFullOnAccount() { + return getUserConfig().isPremium() && storyQualityFull; + } + + public static boolean isStoryQualityFull() { + return MessagesController.getInstance(UserConfig.selectedAccount).isStoryQualityFullOnAccount(); + } + private LongSparseArray cachedIsUserPremiumBlocked = new LongSparseArray<>(); private HashSet loadingIsUserPremiumBlocked = new HashSet<>(); public boolean isUserPremiumBlocked(long userId) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 726e9b46d..a5a18c909 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -43,6 +43,7 @@ import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; import org.telegram.ui.EditWidgetActivity; @@ -104,7 +105,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 139; + public final static int LAST_DB_VERSION = 143; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -704,7 +705,13 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE unconfirmed_auth (data BLOB);").stepThis().dispose(); - database.executeFast("CREATE TABLE saved_reaction_tags (data BLOB);").stepThis().dispose(); + database.executeFast("CREATE TABLE saved_reaction_tags (topic_id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); + + database.executeFast("CREATE TABLE tag_message_id(mid INTEGER, topic_id INTEGER, tag INTEGER, text TEXT);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_idx_tag_message_id ON tag_message_id(tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_text_idx_tag_message_id ON tag_message_id(tag, text COLLATE NOCASE);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_idx_tag_message_id ON tag_message_id(topic_id, tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_text_idx_tag_message_id ON tag_message_id(topic_id, tag, text COLLATE NOCASE);").stepThis().dispose(); database.executeFast("PRAGMA user_version = " + MessagesStorage.LAST_DB_VERSION).stepThis().dispose(); @@ -1933,13 +1940,26 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); cursor = null; - if (!mids.isEmpty()) { - database.executeFast("DELETE FROM messages_v2 WHERE uid = " + selfId + " AND mid IN ("+TextUtils.join(",", mids)+")").stepThis().dispose(); - database.executeFast("DELETE FROM messages_topics WHERE uid = " + selfId + " AND topic_id = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v4 WHERE uid = " + selfId + " AND mid IN ("+TextUtils.join(",", mids)+")").stepThis().dispose(); + cursor = database.queryFinalized("SELECT mid, data FROM messages_v2 WHERE uid = ?", selfId); + while (cursor.next()) { + final int mid = cursor.intValue(0); + if (mids.contains(mid)) continue; + NativeByteBuffer buffer = cursor.byteBufferValue(1); + TLRPC.Message message = TLRPC.Message.TLdeserialize(buffer, buffer.readInt32(false), false); + if (MessageObject.getSavedDialogId(selfId, message) == did) { + mids.add(mid); + } + buffer.reuse(); } + cursor.dispose(); + cursor = null; if (!mids.isEmpty()) { - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0L, false)); + markMessagesAsDeletedInternal(selfId, mids, true, false); + updateDialogsWithDeletedMessages(selfId, -selfId, mids, null, false); + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().markDialogMessageAsDeleted(selfId, mids); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0L, false); + }); } } catch (Exception e) { checkSQLException(e); @@ -2525,6 +2545,7 @@ public class MessagesStorage extends BaseController { forumUnreadCount.put(dialogId, 1); } } + cursor.dispose(); cursor = database.queryFinalized("SELECT did, folder_id, unread_count, unread_count_i FROM dialogs WHERE unread_count > 0 OR flags > 0 UNION ALL " + "SELECT did, folder_id, unread_count, unread_count_i FROM dialogs WHERE unread_count_i > 0"); while (cursor.next()) { @@ -4063,6 +4084,9 @@ public class MessagesStorage extends BaseController { cursor2 = null; database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did + " AND mid != " + last_mid_i + " AND mid != " + last_mid).stepThis().dispose(); + if (did == getUserConfig().getClientUserId()) { + database.executeFast("DELETE FROM messages_topics WHERE uid = " + did + " AND mid != " + last_mid_i + " AND mid != " + last_mid).stepThis().dispose(); + } database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard_topics WHERE uid = " + did).stepThis().dispose(); @@ -4089,6 +4113,9 @@ public class MessagesStorage extends BaseController { database.executeFast("UPDATE dialogs SET unread_count = 0, unread_count_i = 0 WHERE did = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did).stepThis().dispose(); + if (did == getUserConfig().getClientUserId()) { + database.executeFast("DELETE FROM messages_topics WHERE uid = " + did).stepThis().dispose(); + } database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard_topics WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); @@ -4559,10 +4586,138 @@ public class MessagesStorage extends BaseController { }); } + public void searchSavedByTag(TLRPC.Reaction tag, long topic_id, String query, int limit, int offset, Utilities.Callback4, ArrayList, ArrayList, ArrayList> done, boolean includeGroups) { + if (done == null) { + return; + } + storageQueue.postRunnable(() -> { + SQLitePreparedStatement state = null; + SQLiteCursor cursor = null; + SQLiteCursor cursor_groups = null; + try { + final long selfId = getUserConfig().getClientUserId(); + state = database.executeFast("SELECT m.data, m.replydata, m.group_id FROM messages_v2 m INNER JOIN tag_message_id t ON m.mid = t.mid WHERE m.uid = ? AND t.tag = ?" + (!TextUtils.isEmpty(query) ? " AND t.text LIKE '%' || ? || '%'" : "") + (topic_id != 0 ? " AND topic_id = ? " : "") + " ORDER BY m.mid DESC LIMIT ? OFFSET ?"); + + ArrayList users = new ArrayList<>(); +// ArrayList encUsers = new ArrayList<>(); + ArrayList chats = new ArrayList<>(); + ArrayList animatedEmojiToLoad = new ArrayList<>(); + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + ArrayList animatedEmoji = new ArrayList<>(); +// LongSparseArray>> replyMessageOwners = new LongSparseArray<>(); +// LongSparseArray> dialogReplyMessagesIds = new LongSparseArray<>(); + + int pointer = 1; + state.bindLong(pointer++, selfId); + long hash = 0; + if (tag instanceof TLRPC.TL_reactionEmoji) { + hash = ((TLRPC.TL_reactionEmoji) tag).emoticon.hashCode(); + } else if (tag instanceof TLRPC.TL_reactionCustomEmoji) { + hash = ((TLRPC.TL_reactionCustomEmoji) tag).document_id; + } + state.bindLong(pointer++, hash); + if (!TextUtils.isEmpty(query)) { + String q = LocaleController.getInstance().getTranslitString(query); + if (q == null) q = ""; + state.bindString(pointer++, q); + } + if (topic_id != 0) { + state.bindLong(pointer++, topic_id); + } + state.bindInteger(pointer++, limit); + state.bindInteger(pointer++, offset); + + cursor = state.query(new Object[] {}); + state = null; + + ArrayList messageObjects = new ArrayList<>(); + while (cursor.next()) { + long group_id = cursor.longValue(2); + if (group_id != 0 && includeGroups) { + cursor_groups = database.queryFinalized("SELECT data, replydata, group_id FROM messages_v2 WHERE uid = ? AND group_id = ? ORDER BY mid DESC", selfId, group_id); + ArrayList groupmessages = new ArrayList<>(); + while (cursor_groups.next()) { + NativeByteBuffer data = cursor_groups.byteBufferValue(0); + TLRPC.Message groupmessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + groupmessage.readAttachPath(data, selfId); + data.reuse(); + addUsersAndChatsFromMessage(groupmessage, usersToLoad, chatsToLoad, animatedEmojiToLoad); + MessageObject messageObject = new MessageObject(currentAccount, groupmessage, null, null, null, null, null, true, true, 0, false, false, true); + if (groupmessage.reactions != null) { + messageObject.isPrimaryGroupMessage = true; + } + groupmessages.add(messageObject); + } + cursor_groups.dispose(); + messageObjects.addAll(groupmessages); + } else { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data == null) continue; + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + if (message != null) { + message.readAttachPath(data, selfId); + data.reuse(); + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, animatedEmojiToLoad); + if (message.reply_to != null && (message.reply_to.reply_to_msg_id != 0 || message.reply_to.reply_to_random_id != 0)) { + if (!cursor.isNull(1)) { + data = cursor.byteBufferValue(1); + if (data != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.replyMessage.readAttachPath(data, selfId); + data.reuse(); + if (message.replyMessage != null) { + addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad, animatedEmojiToLoad); + } + } + } + } + MessageObject messageObject = new MessageObject(currentAccount, message, null, null, null, null, null, true, true, 0, false, false, true); + messageObjects.add(messageObject); + } + } + } + cursor.dispose(); + +// loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, false); + + if (!usersToLoad.isEmpty()) { + getUsersInternal(TextUtils.join(",", usersToLoad), users); + } + if (!chatsToLoad.isEmpty()) { + getChatsInternal(TextUtils.join(",", chatsToLoad), chats); + } + if (!animatedEmojiToLoad.isEmpty()) { + getAnimatedEmoji(TextUtils.join(",", animatedEmojiToLoad), animatedEmoji); + } + + AndroidUtilities.runOnUIThread(() -> { + done.run(messageObjects, users, chats, animatedEmoji); + }); + + } catch (Exception e) { + FileLog.e(e); + } finally { + if (state != null) { + state.dispose(); + } + if (cursor != null) { + cursor.dispose(); + } + if (cursor_groups != null) { + cursor_groups.dispose(); + } + } + }); + } + public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageReactions reactions) { storageQueue.postRunnable(() -> { SQLiteCursor cursor = null; try { + final long selfId = getUserConfig().getClientUserId(); + TLRPC.TL_messageReactions pastReactions = null; + long topicId = 0; database.beginTransaction(); for (int i = 0; i < 2; i++) { if (i == 0) { @@ -4577,6 +4732,10 @@ public class MessagesStorage extends BaseController { if (message != null) { message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); + if (pastReactions == null) { + pastReactions = message.reactions; + topicId = MessageObject.getSavedDialogId(selfId, message); + } MessageObject.updateReactions(message, reactions); SQLitePreparedStatement state; if (i == 0) { @@ -4594,6 +4753,12 @@ public class MessagesStorage extends BaseController { state.step(); data2.reuse(); state.dispose(); + if (selfId == dialogId) { + database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid = %d", message.id)).stepThis().dispose(); + SQLitePreparedStatement state_tag_message = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + bindMessageTags(state_tag_message, message); + state_tag_message.dispose(); + } } else { data.reuse(); } @@ -4603,6 +4768,9 @@ public class MessagesStorage extends BaseController { cursor = null; } database.commitTransaction(); + if (dialogId == selfId && pastReactions != null) { + onReactionsUpdate(topicId, pastReactions, reactions); + } } catch (Exception e) { checkSQLException(e); } finally { @@ -4616,6 +4784,145 @@ public class MessagesStorage extends BaseController { }); } + private class SavedReactionsUpdate { + long topic_id; + TLRPC.TL_messageReactions old; + TLRPC.TL_messageReactions last; + public SavedReactionsUpdate(long selfId, TLRPC.Message oldMessage, TLRPC.Message newMessage) { + topic_id = MessageObject.getSavedDialogId(selfId, newMessage); + old = oldMessage.reactions; + last = newMessage.reactions; + } + } + + private void onReactionsUpdate(ArrayList reactionUpdates) { + if (reactionUpdates == null || reactionUpdates.isEmpty()) return; + AndroidUtilities.runOnUIThread(() -> { + boolean updated = false; + HashSet topicIds = new HashSet<>(); + LongSparseArray oldTags = new LongSparseArray<>(); + LongSparseArray newTags = new LongSparseArray<>(); + for (int i = 0; i < reactionUpdates.size(); ++i) { + SavedReactionsUpdate pair = reactionUpdates.get(i); + TLRPC.TL_messageReactions a = pair.old; + TLRPC.TL_messageReactions b = pair.last; + + oldTags.clear(); + newTags.clear(); + + if (a != null && a.results != null && a.reactions_as_tags) { + for (int j = 0; j < a.results.size(); ++j) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(j).reaction); + if (reaction != null) { + oldTags.put(reaction.hash, reaction); + } + } + } + if (b != null && b.results != null && b.reactions_as_tags) { + for (int j = 0; j < b.results.size(); ++j) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(j).reaction); + if (reaction != null) { + newTags.put(reaction.hash, reaction); + } + } + } + // delete reactions + for (int j = 0; j < oldTags.size(); ++j) { + long hash = oldTags.keyAt(j); + ReactionsLayoutInBubble.VisibleReaction reaction = oldTags.valueAt(j); + if (!newTags.containsKey(hash)) { + if (getMessagesController().updateSavedReactionTags(pair.topic_id, reaction, false, false)) { + updated = true; + topicIds.add(pair.topic_id); + } + } + } + // add new reactions + for (int j = 0; j < newTags.size(); ++j) { + long hash = newTags.keyAt(j); + ReactionsLayoutInBubble.VisibleReaction reaction = newTags.valueAt(j); + if (!oldTags.containsKey(hash)) { + if (getMessagesController().updateSavedReactionTags(pair.topic_id, reaction, true, false)) { + updated = true; + topicIds.add(pair.topic_id); + } + } + } + } + if (updated && !topicIds.isEmpty()) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } + + private void onReactionsUpdate(long topic_id, TLRPC.TL_messageReactions a, TLRPC.TL_messageReactions b) { + if (a == null || a.results == null || a != null && a.results != null && a.results.isEmpty() && b != null && b.results.isEmpty()) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + LongSparseArray oldTags = new LongSparseArray<>(); + LongSparseArray newTags = new LongSparseArray<>(); + if (a != null && a.results != null && a.reactions_as_tags) { + for (int i = 0; i < a.results.size(); ++i) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(i).reaction); + oldTags.put(reaction.hash, reaction); + } + } + if (b != null && b.results != null && b.reactions_as_tags) { + for (int i = 0; i < b.results.size(); ++i) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(i).reaction); + newTags.put(reaction.hash, reaction); + } + } + boolean updated = false; + // delete reactions + for (int i = 0; i < oldTags.size(); ++i) { + long hash = oldTags.keyAt(i); + ReactionsLayoutInBubble.VisibleReaction reaction = oldTags.valueAt(i); + if (!newTags.containsKey(hash)) { + updated = getMessagesController().updateSavedReactionTags(topic_id, reaction, false, false) || updated; + } + } + // add new reactions + for (int i = 0; i < newTags.size(); ++i) { + long hash = newTags.keyAt(i); + ReactionsLayoutInBubble.VisibleReaction reaction = newTags.valueAt(i); + if (!oldTags.containsKey(hash)) { + updated = getMessagesController().updateSavedReactionTags(topic_id, reaction, true, false) || updated; + } + } + if (updated) { + if (topic_id != 0) { + getMessagesController().updateSavedReactionTags(0); + } + getMessagesController().updateSavedReactionTags(topic_id); + } + }); + } + + private void bindMessageTags(SQLitePreparedStatement state, TLRPC.Message message) throws SQLiteException { + long selfId = getUserConfig().getClientUserId(); + if (message.reactions != null && message.reactions.reactions_as_tags && message.reactions.results != null && !message.reactions.results.isEmpty()) { + final String text = LocaleController.getInstance().getTranslitString(message.message == null ? "" : message.message); + for (TLRPC.ReactionCount result : message.reactions.results) { + if (result.reaction instanceof TLRPC.TL_reactionEmoji || result.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + state.requery(); + state.bindLong(1, message.id); + state.bindLong(2, MessageObject.getSavedDialogId(selfId, message)); + long hash = 0; + if (result.reaction instanceof TLRPC.TL_reactionEmoji) { + hash = ((TLRPC.TL_reactionEmoji) result.reaction).emoticon.hashCode(); + } else if (result.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = ((TLRPC.TL_reactionCustomEmoji) result.reaction).document_id; + } + state.bindLong(3, hash); + state.bindString(4, text == null ? "" : text); + state.step(); + } + } + } + } + public void updateMessageVoiceTranscriptionOpen(long dialogId, int msgId, TLRPC.Message saveFromMessage) { storageQueue.postRunnable(() -> { SQLitePreparedStatement state = null; @@ -10517,6 +10824,7 @@ public class MessagesStorage extends BaseController { boolean databaseInTransaction = false; SQLitePreparedStatement state_messages = null; SQLitePreparedStatement state_messages_topic = null; + SQLitePreparedStatement state_messages_tags = null; SQLitePreparedStatement state_randoms = null; SQLitePreparedStatement state_download = null; SQLitePreparedStatement state_webpage = null; @@ -10532,6 +10840,7 @@ public class MessagesStorage extends BaseController { try { final boolean scheduled = mode == ChatActivity.MODE_SCHEDULED; final boolean saved = mode == ChatActivity.MODE_SAVED; + final long selfId = getUserConfig().getClientUserId(); if (scheduled) { if (withTransaction) { database.beginTransaction(); @@ -10914,6 +11223,8 @@ public class MessagesStorage extends BaseController { mediaTypesChange.put(mid, type); } } + cursor.dispose(); + cursor = null; SparseIntArray mediaTypes = dialogMediaTypes.get(topicKey.dialogId); @@ -10971,6 +11282,7 @@ public class MessagesStorage extends BaseController { if (!messageIdsMap.isEmpty()) { for (int b = 0, N2 = messageIdsMap.size(); b < N2; b++) { long dialogId = messageIdsMap.keyAt(b); + if (dialogId == selfId) continue; StringBuilder messageIds = messageIdsMap.valueAt(b); ArrayList messagesIdsMap = dialogMessagesIdsMap.get(dialogId); ArrayList mentionsIdsMap = dialogMentionsIdsMap.get(dialogId); @@ -11085,7 +11397,6 @@ public class MessagesStorage extends BaseController { createNewTopics.add(message); } - final long selfId = getUserConfig().getClientUserId(); if (updateDialog) { TLRPC.Message lastMessage = messagesMap.get(message.dialog_id); if (lastMessage == null || message.date > lastMessage.date || lastMessage.id > 0 && message.id > lastMessage.id || lastMessage.id < 0 && message.id < lastMessage.id) { @@ -11113,6 +11424,9 @@ public class MessagesStorage extends BaseController { } statement = state_messages_topic; if (selfId == dialogId && MessageObject.getSavedDialogId(selfId, message) != 0) { + if (message.id < 0 && MessageObject.getSavedDialogId(selfId, message) != selfId) { + continue; + } if (changedSavedMessages == null) { changedSavedMessages = new ArrayList<>(); } @@ -11200,6 +11514,16 @@ public class MessagesStorage extends BaseController { if (storyData != null) { storyData.reuse(); } + + if (dialogId == selfId) { + database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid = %d", message.id)).stepThis().dispose(); + if (state_messages_tags == null) { + state_messages_tags = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + } + state_messages_tags.requery(); + bindMessageTags(state_messages_tags, message); + state_messages_tags.step(); + } } if (message.random_id != 0) { @@ -11341,6 +11665,14 @@ public class MessagesStorage extends BaseController { state_media.dispose(); state_media = null; } + if (state_media_topics != null) { + state_media_topics.dispose(); + state_media_topics = null; + } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + state_messages_tags = null; + } if (state_tasks != null) { state_tasks.dispose(); getMessagesController().didAddedNewTask(minDeleteTime, 0, null); @@ -11425,7 +11757,7 @@ public class MessagesStorage extends BaseController { dids.add(key); if (exists) { - if (message == null || (DialogObject.isEncryptedDialog(key) ? message.date > dialog_date : message.id >= last_mid) || message.send_state != 0 && ((message.flags & TLRPC.MESSAGE_FLAG_EDITED) == 0 || message.id >= last_mid)) { + if (message == null || (DialogObject.isEncryptedDialog(key) ? message.date > dialog_date : message.id >= last_mid) || message.send_state != 0 && (message.flags & TLRPC.MESSAGE_FLAG_EDITED) == 0) { state_dialogs_update.requery(); state_dialogs_update.bindInteger(1, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); state_dialogs_update.bindInteger(2, old_unread_count + unread_count); @@ -11700,6 +12032,12 @@ public class MessagesStorage extends BaseController { if (state_webpage != null) { state_webpage.dispose(); } + if (state_media_topics != null) { + state_media_topics.dispose(); + } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + } if (state_media != null) { state_media.dispose(); } @@ -12383,6 +12721,9 @@ public class MessagesStorage extends BaseController { SQLiteCursor cursor = null; SQLitePreparedStatement state = null; try { + if (getUserConfig().getClientUserId() == dialogId) { + database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid IN(%s)", TextUtils.join(",", messages))).stepThis().dispose(); + } ArrayList dialogsIds = new ArrayList<>(); if (scheduled) { String ids = TextUtils.join(",", messages); @@ -12408,6 +12749,8 @@ public class MessagesStorage extends BaseController { broadcastScheduledMessagesChange(dialogsToUpdate.get(a)); } } else { + long currentUser = getUserConfig().getClientUserId(); + ArrayList unknownMessages = new ArrayList<>(messages); ArrayList unknownMessagesInTopics = new ArrayList<>(messages); LongSparseArray dialogsToUpdate = new LongSparseArray<>(); @@ -12419,8 +12762,8 @@ public class MessagesStorage extends BaseController { ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); ArrayList topicUpdatesInUi = null; + ArrayList deletedMessages = currentUser == dialogId || dialogId == 0 ? new ArrayList<>() : null; - long currentUser = getUserConfig().getClientUserId(); if (dialogId != 0) { cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, data, read_state, out, mention, mid FROM messages_v2 WHERE mid IN(%s) AND uid = %d", ids, dialogId)); } else { @@ -12461,6 +12804,9 @@ public class MessagesStorage extends BaseController { if (data != null) { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); message.readAttachPath(data, currentUser); + if (deletedMessages != null) { + deletedMessages.add(message); + } data.reuse(); if (DialogObject.isEncryptedDialog(did) || deleteFiles) { addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false); @@ -12830,6 +13176,36 @@ public class MessagesStorage extends BaseController { database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", dialogId)).stepThis().dispose(); } } + if (deletedMessages != null && !deletedMessages.isEmpty()) { + AndroidUtilities.runOnUIThread(() -> { + boolean changed = false; + HashSet topicIds = new HashSet<>(); + for (TLRPC.Message msg : deletedMessages) { + if (getMessagesController().processDeletedReactionTags(msg)) { + topicIds.add(MessageObject.getSavedDialogId(currentUser, msg)); + changed = true; + } + } + if (changed) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } else if (deletedMessages != null && deletedMessages.isEmpty()) { + AndroidUtilities.runOnUIThread(() -> { + HashSet topicIds = new HashSet<>(); + boolean changed = false; + long[] topic_id = new long[1]; + for (int i = 0; i < messages.size(); ++i) { + if (getMediaDataController().processDeletedMessage(messages.get(i), topic_id)) { + topicIds.add(topic_id[0]); + changed = true; + } + } + if (changed) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } if (!unknownMessagesInTopics.isEmpty()) { if (dialogId == 0) { database.executeFast("UPDATE media_counts_topics SET old = 1 WHERE 1").stepThis().dispose(); @@ -13832,6 +14208,7 @@ public class MessagesStorage extends BaseController { SQLitePreparedStatement state_messages_topics = null; SQLitePreparedStatement state_media = null; SQLitePreparedStatement state_media_topics = null; + SQLitePreparedStatement state_messages_tags = null; SQLitePreparedStatement state_polls = null; SQLitePreparedStatement state_webpage = null; SQLitePreparedStatement state_tasks = null; @@ -13900,6 +14277,7 @@ public class MessagesStorage extends BaseController { closeHolesInMedia(dialogId, minId, maxId, -1, threadMessageId); } int count = messages.messages.size(); + final long selfId = getUserConfig().getClientUserId(); //load_type == 0 ? backward loading //load_type == 1 ? forward loading @@ -13910,6 +14288,7 @@ public class MessagesStorage extends BaseController { ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); ArrayList changedSavedMessages = null; + ArrayList reactionUpdates = dialogId == selfId ? new ArrayList<>() : null; Integer lastMessageId = null; Long lastMessageGroupId = null; @@ -13923,7 +14302,16 @@ public class MessagesStorage extends BaseController { int minDeleteTime = Integer.MAX_VALUE; HashMap botKeyboards = null; long channelId = 0; - final long selfId = getUserConfig().getClientUserId(); + final boolean self = selfId == dialogId; + if (self) { + ArrayList ids = new ArrayList<>(); + for (int a = 0; a < count; a++) { + TLRPC.Message message = messages.messages.get(a); + ids.add(message.id); + } + database.executeFast("DELETE FROM tag_message_id WHERE mid IN (" + TextUtils.join(",", ids) + ")").stepThis().dispose(); + state_messages_tags = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + } for (int a = 0; a < count; a++) { TLRPC.Message message = messages.messages.get(a); if (lastMessageId == null && message != null || lastMessageId != null && lastMessageId < message.id) { @@ -13944,6 +14332,9 @@ public class MessagesStorage extends BaseController { TLRPC.Message oldMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); oldMessage.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); + if (reactionUpdates != null) { + reactionUpdates.add(new SavedReactionsUpdate(selfId, oldMessage, message)); + } int send_state = cursor.intValue(5); if (send_state != 3) { if (MessageObject.getFileName(oldMessage).equals(MessageObject.getFileName(message))) { @@ -14150,6 +14541,10 @@ public class MessagesStorage extends BaseController { } currentState.step(); + if (i == 0 && state_messages_tags != null) { + bindMessageTags(state_messages_tags, message); + } + if (repliesData != null) { repliesData.reuse(); } @@ -14248,6 +14643,10 @@ public class MessagesStorage extends BaseController { state_messages = null; state_messages_topics.dispose(); state_messages_topics = null; + if (state_messages_tags != null) { + state_messages_tags.dispose(); + state_messages_tags = null; + } state_media.dispose(); state_media = null; if (state_webpage != null) { @@ -14302,6 +14701,7 @@ public class MessagesStorage extends BaseController { } }); } + onReactionsUpdate(reactionUpdates); } } catch (Exception e) { checkSQLException(e); @@ -14312,6 +14712,9 @@ public class MessagesStorage extends BaseController { if (state_messages_topics != null) { state_messages_topics.dispose(); } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + } if (state_messages != null) { state_messages.dispose(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 0294d98d2..3c6756039 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -9,6 +9,7 @@ package org.telegram.messenger; import android.os.SystemClock; +import android.util.Log; import android.util.SparseArray; import android.view.View; @@ -228,6 +229,9 @@ public class NotificationCenter { public static final int savedMessagesDialogsUpdate = totalEvents++; public static final int savedReactionTagsUpdate = totalEvents++; public static final int userIsPremiumBlockedUpadted = totalEvents++; + public static final int savedMessagesForwarded = totalEvents++; + public static final int emojiKeywordsLoaded = totalEvents++; + public static final int storyQualityUpdate = totalEvents++; //global public static final int pushMessagesUpdated = totalEvents++; @@ -507,7 +511,7 @@ public class NotificationCenter { } public void postNotificationName(int id, Object... args) { - boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations || id == didReplacedPhotoInMemCache || id == closeChats || id == invalidateMotionBackground; + boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations || id == didReplacedPhotoInMemCache || id == closeChats || id == invalidateMotionBackground || id == needCheckSystemBarColors; ArrayList expiredIndices = null; if (!allowDuringAnimation && allowedNotifications.size() > 0) { int size = allowedNotifications.size(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java index 1f6b675aa..7d354ba0d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java @@ -2,29 +2,23 @@ package org.telegram.messenger; import android.os.Bundle; import android.text.TextUtils; +import android.util.Log; import androidx.collection.LongSparseArray; -import com.google.android.exoplayer2.util.Log; -import com.google.android.exoplayer2.util.Util; - import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; -import org.telegram.SQLite.SQLiteException; import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Cells.TextCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.LaunchActivity; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Objects; @@ -98,6 +92,9 @@ public class SavedMessagesController { allDialogs.addAll(dialogs); if (notify) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.savedMessagesDialogsUpdate); + if (!hasDialogs() && MessagesController.getInstance(currentAccount).savedViewAsChats) { + MessagesController.getInstance(currentAccount).setSavedViewAs(false); + } } } @@ -111,6 +108,15 @@ public class SavedMessagesController { return cachedDialogs.size(); } + public boolean hasDialogs() { + if (getAllCount() <= 0) return false; + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + if (allDialogs.size() == 1 && allDialogs.get(0).dialogId == selfId) { + return false; + } + return true; + } + public int getLoadedCount() { return loadedDialogs.size(); } @@ -191,20 +197,21 @@ public class SavedMessagesController { return false; } - public void preloadDialogs() { + public void preloadDialogs(boolean cache) { if (!dialogsLoaded) { - loadDialogs(); + loadDialogs(cache); } } - public void loadDialogs() { + public void loadDialogs(boolean onlyCache) { + loadingCacheOnly = onlyCache; if (dialogsLoading || dialogsEndReached || loadingCache) { return; } if (!loadedCache) { - loadCache(this::loadDialogs); + loadCache(() -> loadDialogs(false)); return; - } + } else if (onlyCache) return; dialogsLoading = true; TLRPC.TL_messages_getSavedDialogs req = new TLRPC.TL_messages_getSavedDialogs(); @@ -365,10 +372,18 @@ public class SavedMessagesController { found = true; if (d.top_message_id < message.id || message.id < 0 && message.date > d.getDate()) { changed = true; + if (d.top_message_id < message.id) { + int count = 0; + for (int k = 0; k < inputMessages.size(); ++k) { + if (inputMessages.get(k).id > d.top_message_id) { + count++; + } + } + d.messagesCount += count; + } d.message = new MessageObject(currentAccount, message, false, false); d.top_message_id = d.message.getId(); } - dialogsCountToCheck.add(d.dialogId); break; } } @@ -387,10 +402,18 @@ public class SavedMessagesController { found = true; if (d.top_message_id < message.id || message.id < 0 && message.date > d.getDate()) { changed = true; + if (d.top_message_id < message.id) { + int count = 0; + for (int k = 0; k < inputMessages.size(); ++k) { + if (inputMessages.get(k).id > d.top_message_id) { + count++; + } + } + d.messagesCount += count; + } d.message = new MessageObject(currentAccount, message, false, false); d.top_message_id = d.message.getId(); } - dialogsCountToCheck.add(d.dialogId); break; } } @@ -403,9 +426,6 @@ public class SavedMessagesController { changed = true; } } - if (!dialogsCountToCheck.isEmpty()) { - updateDialogsCount(dialogsCountToCheck); - } return changed; } @@ -432,6 +452,7 @@ public class SavedMessagesController { if (d.dialogId == dialogId) { if (d.messagesCount != messagesCount) { d.messagesCount = messagesCount; + d.messagesCountLoaded = true; return true; } break; @@ -519,7 +540,7 @@ public class SavedMessagesController { dialogsCount = 0; dialogsEndReached = false; update(); - loadDialogs(); + loadDialogs(false); } public void deleteDialog(long did) { @@ -534,6 +555,14 @@ public class SavedMessagesController { update(); } + public void deleteAllDialogs() { + dialogsCount = 0; + allDialogs.clear(); + loadedDialogs.clear(); + cachedDialogs.clear(); + update(); + } + private int removeDialog(long did) { int acount = 0; for (int i = 0; i < allDialogs.size(); ++i) { @@ -565,7 +594,7 @@ public class SavedMessagesController { saveCacheSchedule(); } - public boolean updatePinned(ArrayList dialogIds, boolean pin) { + public boolean updatePinned(ArrayList dialogIds, boolean pin, boolean toServer) { ArrayList currentOrder = getCurrentPinnedOrder(allDialogs); ArrayList newOrder = new ArrayList<>(currentOrder); for (int i = dialogIds.size() - 1; i >= 0; --i) { @@ -585,9 +614,16 @@ public class SavedMessagesController { return false; } if (!sameOrder(currentOrder, newOrder)) { - updatePinnedOrderToServer(newOrder); + if (toServer) { + updatePinnedOrderToServer(newOrder); + return true; + } else { + final boolean updateLoaded = updatePinnedOrder(loadedDialogs, newOrder); + final boolean updateCached = updatePinnedOrder(cachedDialogs, newOrder); + return updateLoaded || updateCached; + } } - return true; + return false; } public boolean updatePinnedOrder(ArrayList newOrder) { @@ -636,18 +672,9 @@ public class SavedMessagesController { TLRPC.TL_updateSavedDialogPinned upd = (TLRPC.TL_updateSavedDialogPinned) update; if (!(upd.peer instanceof TLRPC.TL_dialogPeer)) return false; long dialogId = DialogObject.getPeerDialogId(((TLRPC.TL_dialogPeer) upd.peer).peer); - boolean changed = false; - ArrayList[] arraysToCheck = new ArrayList[] { loadedDialogs, cachedDialogs }; - for (int a = 0; a < arraysToCheck.length; ++a) { - for (int i = 0; i < arraysToCheck[a].size(); ++i) { - SavedDialog d = arraysToCheck[a].get(i); - if (d.dialogId == dialogId && d.pinned != upd.pinned) { - d.pinned = upd.pinned; - changed = true; - } - } - } - return changed; + ArrayList ids = new ArrayList<>(); + ids.add(dialogId); + return updatePinned(ids, upd.pinned, false); } else if (update instanceof TLRPC.TL_updatePinnedSavedDialogs) { TLRPC.TL_updatePinnedSavedDialogs upd = (TLRPC.TL_updatePinnedSavedDialogs) update; ArrayList newOrder = new ArrayList<>(upd.order.size()); @@ -731,49 +758,8 @@ public class SavedMessagesController { return true; } - private void updateDialogsCount(HashSet dialogIds) { - final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); - MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount); - messagesStorage.getStorageQueue().postRunnable(() -> { - SQLiteDatabase db = messagesStorage.getDatabase(); - LongSparseArray countResult = new LongSparseArray<>(); - SQLiteCursor cursor = null; - try { - for (long did : dialogIds) { - cursor = db.queryFinalized("SELECT COUNT(*) FROM messages_topics WHERE uid = ? AND topic_id = ?", selfId, did); - if (cursor.next()) { - countResult.put(did, cursor.intValue(0)); - } - cursor.dispose(); - } - } catch (Exception e) { - FileLog.e(e); - } finally { - if (cursor != null) { - cursor.dispose(); - cursor = null; - } - } - AndroidUtilities.runOnUIThread(() -> { - boolean changed = false; - for (int i = 0; i < countResult.size(); ++i) { - long did = countResult.keyAt(i); - int count = countResult.valueAt(i); - - SavedDialog d = findSavedDialog(did); - if (d != null && d.messagesCount != count) { - d.messagesCount = count; - changed = true; - } - } - if (changed) { - update(); - } - }); - }); - } - private boolean loadingCache, loadedCache; + private boolean loadingCacheOnly; private void loadCache(Runnable whenDone) { if (loadingCache) { return; @@ -802,6 +788,8 @@ public class SavedMessagesController { d.localDate = cursor.intValue(1); d.top_message_id = cursor.intValue(2); d.pinnedOrder = cursor.intValue(3); + final int flags = cursor.intValue(4); + d.messagesCountLoaded = (flags & 1) != 0; d.pinned = d.pinnedOrder != 999; d.messagesCount = cursor.intValue(7); if (d.dialogId < 0) { @@ -855,7 +843,7 @@ public class SavedMessagesController { cachedDialogs.addAll(dialogs); updateAllDialogs(true); - if (whenDone != null) { + if (whenDone != null && !loadingCacheOnly) { whenDone.run(); } }); @@ -974,7 +962,7 @@ public class SavedMessagesController { state.bindInteger(2, d.getDate()); state.bindInteger(3, d.top_message_id); state.bindInteger(4, d.pinned ? i : 999); - state.bindInteger(5, 0); + state.bindInteger(5, d.messagesCountLoaded ? 1 : 0); state.bindInteger(6, 0); state.bindInteger(7, 0); state.bindInteger(8, d.messagesCount); @@ -1022,6 +1010,8 @@ public class SavedMessagesController { public MessageObject message; public int messagesCount; + public boolean messagesCountLoaded; + // used only in cache private int localDate; @@ -1032,7 +1022,7 @@ public class SavedMessagesController { if (message == null || message.messageOwner == null) { return localDate; } - if ((message.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0) { + if ((message.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 && !message.messageOwner.edit_hide) { return message.messageOwner.edit_date; } return message.messageOwner.date; @@ -1080,23 +1070,28 @@ public class SavedMessagesController { lastFragment.presentFragment(new ChatActivity(args)); } + public void checkSavedDialogCount(long dialogId) { + SavedDialog d = findSavedDialog(dialogId); + if (d != null && !d.messagesCountLoaded) { + hasSavedMessages(dialogId, null); + } + } + private final LongSparseArray>> checkMessagesCallbacks = new LongSparseArray<>(); public void hasSavedMessages(long did, Utilities.Callback whenDone) { - if (whenDone == null) return; - final SavedDialog savedDialog = findSavedDialog(did); - if (savedDialog != null && savedDialog.messagesCount > 0) { - whenDone.run(true); + if (savedDialog != null && savedDialog.messagesCount > 0 && savedDialog.messagesCountLoaded) { + if (whenDone != null) whenDone.run(true); return; } ArrayList> existingCallbacks = checkMessagesCallbacks.get(did); if (existingCallbacks != null) { - existingCallbacks.add(whenDone); + if (whenDone != null) existingCallbacks.add(whenDone); return; } existingCallbacks = new ArrayList<>(); - existingCallbacks.add(whenDone); + if (whenDone != null) existingCallbacks.add(whenDone); checkMessagesCallbacks.put(did, existingCallbacks); TLRPC.TL_messages_getSavedHistory req = new TLRPC.TL_messages_getSavedHistory(); @@ -1124,9 +1119,12 @@ public class SavedMessagesController { if (!r.messages.isEmpty()) { SavedDialog dialog = SavedDialog.fromMessage(currentAccount, r.messages.get(0)); dialog.messagesCount = count; + dialog.messagesCountLoaded = true; cachedDialogs.add(dialog); update(); } + } else { + update(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 6443c9c13..811681743 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -2189,6 +2189,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe a1--; } } + getNotificationCenter().postNotificationNameOnUIThread(NotificationCenter.savedMessagesForwarded, newMessagesByIds); Integer value = getMessagesController().dialogs_read_outbox_max.get(peer); if (value == null) { value = getMessagesStorage().getDialogReadMax(true, peer); @@ -2958,7 +2959,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return voteSendTime.get(pollId, 0L); } - public void sendReaction(MessageObject messageObject, ArrayList visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, ChatActivity parentFragment, Runnable callback) { + public void sendReaction(MessageObject messageObject, ArrayList visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, BaseFragment parentFragment, Runnable callback) { if (messageObject == null || parentFragment == null) { return; } @@ -4092,6 +4093,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe inputWebPage.url = mediaWebPage.webpage.url; inputWebPage.force_large_media = mediaWebPage.force_large_media; inputWebPage.force_small_media = mediaWebPage.force_small_media; + inputWebPage.optional = true; reqSend.media = inputWebPage; if (replyToStoryItem != null) { reqSend.reply_to = createReplyInput(replyToStoryItem); @@ -5102,10 +5104,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } } putToDelayedMessages(location, message); - if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) { - getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo, false); - } else { - getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo); + if (message.obj.videoEditedInfo == null || !message.obj.videoEditedInfo.notReadyYet) { + if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) { + getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo, false); + } else { + getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo); + } } putToUploadingMessages(message.obj); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 3fbbfce0e..f3b976f3e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -238,7 +238,6 @@ public class SharedConfig { public static int keepMedia = CacheByChatsController.KEEP_MEDIA_ONE_MONTH; //deprecated public static int lastKeepMediaCheckTime; public static int lastLogsCheckTime; - public static int searchMessagesAsListHintShows; public static int textSelectionHintShows; public static int scheduledOrNoSoundHintShows; public static long scheduledOrNoSoundHintSeenAt; @@ -310,7 +309,6 @@ public class SharedConfig { public static int messageSeenHintCount; public static int emojiInteractionsHintCount; public static int dayNightThemeSwitchHintCount; - public static boolean forceLessData; public static int callEncryptionHintDisplayedCount; public static TLRPC.TL_help_appUpdate pendingAppUpdate; @@ -616,7 +614,6 @@ public class SharedConfig { debugWebView = preferences.getBoolean("debugWebView", false); lastKeepMediaCheckTime = preferences.getInt("lastKeepMediaCheckTime", 0); lastLogsCheckTime = preferences.getInt("lastLogsCheckTime", 0); - searchMessagesAsListHintShows = preferences.getInt("searchMessagesAsListHintShows", 0); searchMessagesAsListUsed = preferences.getBoolean("searchMessagesAsListUsed", false); stickersReorderingHintUsed = preferences.getBoolean("stickersReorderingHintUsed", false); storyReactionsLongPressHint = preferences.getBoolean("storyReactionsLongPressHint", false); @@ -649,7 +646,6 @@ public class SharedConfig { payByInvoice = preferences.getBoolean("payByInvoice", false); photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); multipleReactionsPromoShowed = preferences.getBoolean("multipleReactionsPromoShowed", false); - forceLessData = preferences.getBoolean("forceLessData", false); callEncryptionHintDisplayedCount = preferences.getInt("callEncryptionHintDisplayedCount", 0); loadDebugConfig(preferences); @@ -1003,13 +999,6 @@ public class SharedConfig { editor.apply(); } - public static void increaseSearchAsListHintShows() { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("searchMessagesAsListHintShows", ++searchMessagesAsListHintShows); - editor.apply(); - } - public static void setKeepMedia(int value) { keepMedia = value; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); @@ -1545,11 +1534,6 @@ public class SharedConfig { preferences.edit().putInt("emojiInteractionsHintCount", emojiInteractionsHintCount).apply(); } - public static void setForceLessData(boolean value) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - preferences.edit().putBoolean("forceLessData", forceLessData = value).apply(); - } - public static void updateDayNightThemeSwitchHintCount(int count) { dayNightThemeSwitchHintCount = count; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java index e07eae3b5..4155f19d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java @@ -1001,7 +1001,7 @@ public class TopicsController extends BaseController { } } - public void loadTopic(long chatId, int topicId, Runnable runnable) { + public void loadTopic(long chatId, long topicId, Runnable runnable) { getMessagesStorage().loadTopics(-chatId, topics -> { AndroidUtilities.runOnUIThread(() -> { if (BuildVars.LOGS_ENABLED) { @@ -1015,7 +1015,7 @@ public class TopicsController extends BaseController { } else { ArrayList topicToReload = new ArrayList<>(); TLRPC.TL_forumTopic topic = new TLRPC.TL_forumTopic(); - topic.id = topicId; + topic.id = (int) topicId; reloadTopics(chatId, topicToReload, runnable); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 402c69cc5..b4a8c9e44 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -499,6 +499,16 @@ public class Utilities { return Math.max(Math.min(value, maxValue), minValue); } + public static double clamp(double value, double maxValue, double minValue) { + if (Double.isNaN(value)) { + return minValue; + } + if (Double.isInfinite(value)) { + return maxValue; + } + return Math.max(Math.min(value, maxValue), minValue); + } + public static String generateRandomString() { return generateRandomString(16); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 0c9f6bf85..b64d51bd2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -11,11 +11,10 @@ package org.telegram.messenger; import android.app.Service; import android.content.Intent; import android.os.IBinder; + import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import com.google.android.exoplayer2.util.Log; - public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate { private NotificationCompat.Builder builder; @@ -89,11 +88,7 @@ public class VideoEncodingService extends Service implements NotificationCenter. Boolean enc = (Boolean) args[3]; int currentProgress = (int) (progress * 100); builder.setProgress(100, currentProgress, currentProgress == 0); - try { - NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); - } catch (Throwable e) { - FileLog.e(e); - } + updateNotification(); } } else if (id == NotificationCenter.fileUploaded || id == NotificationCenter.fileUploadFailed) { String fileName = (String) args[0]; @@ -110,12 +105,27 @@ public class VideoEncodingService extends Service implements NotificationCenter. } } + private void updateNotification() { + try { + MediaController.VideoConvertMessage message = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (message == null) { + return; + } + NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + } catch (Throwable e) { + FileLog.e(e); + } + } + public int onStartCommand(Intent intent, int flags, int startId) { if (isRunning()) { return Service.START_NOT_STICKY; } - instance = this; MediaController.VideoConvertMessage videoConvertMessage = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (videoConvertMessage == null) { + return Service.START_NOT_STICKY; + } + instance = this; if (builder == null) { NotificationsController.checkOtherNotificationsChannel(); builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext, NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); @@ -124,7 +134,6 @@ public class VideoEncodingService extends Service implements NotificationCenter. builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName)); } - setCurrentMessage(videoConvertMessage); try { startForeground(4, builder.build()); @@ -132,7 +141,7 @@ public class VideoEncodingService extends Service implements NotificationCenter. //ignore ForegroundServiceStartNotAllowedException FileLog.e(e); } - AndroidUtilities.runOnUIThread(() -> NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build())); + AndroidUtilities.runOnUIThread(this::updateNotification); return Service.START_NOT_STICKY; } @@ -169,7 +178,7 @@ public class VideoEncodingService extends Service implements NotificationCenter. NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); if (isRunning()) { - NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + updateNotification(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java index 53a6283c5..3f8b016f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java @@ -86,7 +86,7 @@ public class VideoPlayerHolderBase { long startTime; - public void preparePlayer(Uri uri, boolean audioDisabled) { + public void preparePlayer(Uri uri, boolean audioDisabled, float speed) { this.audioDisabled = audioDisabled; this.currentAccount = currentAccount; this.contentUri = uri; @@ -99,13 +99,14 @@ public class VideoPlayerHolderBase { return; } ensurePlayerCreated(audioDisabled); + videoPlayer.setPlaybackSpeed(speed); videoPlayer.preparePlayer(uri, "other", FileLoader.PRIORITY_LOW); videoPlayer.setPlayWhenReady(false); videoPlayer.setWorkerQueue(dispatchQueue); }); } - public void start(boolean paused, Uri uri, long position, boolean audioDisabled) { + public void start(boolean paused, Uri uri, long position, boolean audioDisabled, float speed) { startTime = System.currentTimeMillis(); this.audioDisabled = audioDisabled; this.paused = paused; @@ -118,6 +119,7 @@ public class VideoPlayerHolderBase { } if (videoPlayer == null) { ensurePlayerCreated(audioDisabled); + videoPlayer.setPlaybackSpeed(speed); videoPlayer.preparePlayer(uri, "other"); videoPlayer.setWorkerQueue(dispatchQueue); if (!paused) { @@ -280,6 +282,17 @@ public class VideoPlayerHolderBase { } } + public void setSpeed(float speed) { + if (released) { + return; + } + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.setPlaybackSpeed(speed); + } + }); + } + public void play() { if (released) { return; @@ -304,6 +317,31 @@ public class VideoPlayerHolderBase { }); } + public void play(float speed) { + if (released) { + return; + } + if (!paused) { + return; + } + paused = false; + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + if (pendingSeekTo > 0) { + videoPlayer.seekTo(pendingSeekTo); + pendingSeekTo = 0; + } + videoPlayer.setPlaybackSpeed(speed); + videoPlayer.setPlayWhenReady(true); + } + }); + } + public void setAudioEnabled(boolean enabled, boolean prepared) { boolean disabled = !enabled; if (audioDisabled == disabled) { @@ -430,16 +468,6 @@ public class VideoPlayerHolderBase { return contentUri; } - public void setPlaybackSpeed(float currentVideoSpeed) { - dispatchQueue.postRunnable(() -> { - if (videoPlayer == null) { - return; - } - videoPlayer.setPlaybackSpeed(currentVideoSpeed); - }); - - } - private Runnable onSeekUpdate; public void setOnSeekUpdate(Runnable onSeekUpdate) { this.onSeekUpdate = onSeekUpdate; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 5f373304c..e2624740b 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -379,7 +379,7 @@ public class ConnectionsManager extends BaseController { if (BuildVars.LOGS_ENABLED) { FileLog.d("java received " + resp + " error = " + error + " messageId = " + requestMsgId); } - FileLog.dumpResponseAndRequest(object, resp, error, requestMsgId, finalStartRequestTime, requestToken); + FileLog.dumpResponseAndRequest(currentAccount, object, resp, error, requestMsgId, finalStartRequestTime, requestToken); final TLObject finalResponse = resp; final TLRPC.TL_error finalError = error; Utilities.stageQueue.postRunnable(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 272156eaf..c488f5ad8 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -23,6 +23,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.tgnet.tl.TL_stories; @@ -76,7 +77,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 172; + public static final int LAYER = 173; public static class TL_stats_megagroupStats extends TLObject { public static final int constructor = 0xef7ff916; @@ -28863,6 +28864,8 @@ public class TLRPC { public String title; public int count; + public long hash; // custom + public static TL_savedReactionTag TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_savedReactionTag.constructor != constructor) { if (exception) { @@ -55720,6 +55723,8 @@ public class TLRPC { public static abstract class Reaction extends TLObject { + public long tag_long_id; // custom + public static Reaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Reaction result = null; switch (constructor) { @@ -60820,7 +60825,7 @@ public class TLRPC { stream.writeInt32(constructor); stream.writeInt32(flags); peer.serializeToStream(stream); - if ((flags & 2) != 0) { + if ((flags & 4) != 0) { saved_peer_id.serializeToStream(stream); } if ((flags & 1) != 0) { @@ -64959,9 +64964,8 @@ public class TLRPC { return result; } - public Boolean documentExists; public Document getDocument() { - if (alt_document != null && ApplicationLoader.useLessData()) { + if (alt_document != null && !MessagesController.isStoryQualityFull()) { return alt_document; } return document; @@ -75061,8 +75065,10 @@ public class TLRPC { } public static class TL_messages_getSavedReactionTags extends TLObject { - public static final int constructor = 0x761ddacf; + public static final int constructor = 0x3637e05b; + public int flags; + public InputPeer peer; public long hash; @Override @@ -75073,6 +75079,10 @@ public class TLRPC { @Override public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + peer.serializeToStream(stream); + } stream.writeInt64(hash); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 0bddabec4..17585224c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -24,6 +24,7 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.SpannableString; @@ -147,8 +148,6 @@ public class ActionBar extends FrameLayout { private View.OnTouchListener interceptTouchEventListener; private final Theme.ResourcesProvider resourcesProvider; - private PorterDuff.Mode colorFilterMode = PorterDuff.Mode.MULTIPLY; - SizeNotifierFrameLayout contentView; boolean blurredBackground; public Paint blurScrimPaint = new Paint(); @@ -173,10 +172,6 @@ public class ActionBar extends FrameLayout { }); } - public void setColorFilterMode(PorterDuff.Mode colorFilterMode) { - this.colorFilterMode = colorFilterMode; - } - public INavigationLayout.BackButtonState getBackButtonState() { if (backButtonDrawable instanceof INavigationLayout.IBackButtonDrawable) { return ((INavigationLayout.IBackButtonDrawable) backButtonDrawable).getBackButtonState(); @@ -191,9 +186,6 @@ public class ActionBar extends FrameLayout { backButtonImageView = new ImageView(getContext()); backButtonImageView.setScaleType(ImageView.ScaleType.CENTER); backButtonImageView.setBackgroundDrawable(Theme.createSelectorDrawable(itemsBackgroundColor)); - if (itemsColor != 0) { - backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, colorFilterMode)); - } backButtonImageView.setPadding(dp(1), 0, 0, 0); addView(backButtonImageView, LayoutHelper.createFrame(54, 54, Gravity.LEFT | Gravity.TOP)); @@ -228,6 +220,8 @@ public class ActionBar extends FrameLayout { MenuDrawable menuDrawable = (MenuDrawable) drawable; menuDrawable.setBackColor(actionBarColor); menuDrawable.setIconColor(itemsColor); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN)); } } @@ -359,6 +353,7 @@ public class ActionBar extends FrameLayout { } backButtonImageView.setVisibility(resource == 0 ? GONE : VISIBLE); backButtonImageView.setImageResource(resource); + backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN)); } private void createSubtitleTextView() { @@ -1599,18 +1594,21 @@ public class ActionBar extends FrameLayout { Drawable drawable = backButtonImageView.getDrawable(); if (drawable instanceof BackDrawable) { ((BackDrawable) drawable).setRotatedColor(color); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); } } } else { itemsColor = color; if (backButtonImageView != null) { if (itemsColor != 0) { - backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, colorFilterMode)); Drawable drawable = backButtonImageView.getDrawable(); if (drawable instanceof BackDrawable) { ((BackDrawable) drawable).setColor(color); - } else if (drawable instanceof MenuDrawable) { + } else if (drawable instanceof MenuDrawable) { ((MenuDrawable) drawable).setIconColor(color); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); } } } 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 9e9019ad6..a02dc2de3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -64,6 +64,7 @@ import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider; import org.telegram.ui.Components.GroupCallPip; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.LogoutActivity; import org.telegram.ui.Stories.StoryViewer; import java.util.ArrayList; @@ -1627,6 +1628,12 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F fragmentsStack.add(position, fragment); onFragmentStackChanged("addFragmentToStack"); } + if (!useAlphaAnimations) { + setVisibility(VISIBLE); + if (backgroundView != null) { + backgroundView.setVisibility(VISIBLE); + } + } return true; } @@ -2035,6 +2042,11 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F removeFragmentFromStackInternal(fragmentsStack.get(a), false); a--; } + if (backgroundView != null) { + backgroundView.animate().alpha(0.0f).setDuration(180).withEndAction(() -> { + backgroundView.setVisibility(View.GONE); + }).start(); + } } @Keep diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index ddeb8f934..d16129028 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -508,6 +508,13 @@ public class ActionBarMenu extends LinearLayout { return null; } + public void setItemVisibility(int id, int visibility) { + View item = getItem(id); + if (item != null) { + item.setVisibility(visibility); + } + } + @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index 855e4a0a9..1121b5970 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -32,6 +32,7 @@ import android.transition.TransitionManager; import android.transition.TransitionSet; import android.transition.TransitionValues; import android.transition.Visibility; +import android.util.Log; import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; @@ -990,7 +991,7 @@ public class ActionBarMenuItem extends FrameLayout { boolean visible = !currentSearchFilters.isEmpty(); ArrayList localFilters = new ArrayList<>(currentSearchFilters); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && searchContainer.getTag() != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && searchContainer != null && searchContainer.getTag() != null) { TransitionSet transition = new TransitionSet(); ChangeBounds changeBounds = new ChangeBounds(); changeBounds.setDuration(150); @@ -1055,11 +1056,13 @@ public class ActionBarMenuItem extends FrameLayout { TransitionManager.beginDelayedTransition(searchFilterLayout, transition); } - for (int i = 0; i < searchFilterLayout.getChildCount(); i++) { - boolean removed = localFilters.remove(((SearchFilterView) searchFilterLayout.getChildAt(i)).getFilter()); - if (!removed) { - searchFilterLayout.removeViewAt(i); - i--; + if (searchFilterLayout != null) { + for (int i = 0; i < searchFilterLayout.getChildCount(); i++) { + boolean removed = localFilters.remove(((SearchFilterView) searchFilterLayout.getChildAt(i)).getFilter()); + if (!removed) { + searchFilterLayout.removeViewAt(i); + i--; + } } } @@ -2041,10 +2044,11 @@ public class ActionBarMenuItem extends FrameLayout { reactionCount.count = 1; reactionCount.reaction = data.reaction.toTLReaction(); - reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, UserConfig.selectedAccount, this, reactionCount, false, resourcesProvider) { + reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, UserConfig.selectedAccount, this, reactionCount, false, true, resourcesProvider) { @Override protected void updateColors(float progress) { lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider), progress); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, 0x5affffff, progress); } @Override @@ -2052,6 +2056,7 @@ public class ActionBarMenuItem extends FrameLayout { return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS; } }; + reactionButton.isTag = true; reactionButton.width = dp(44.33f); reactionButton.height = dp(28); reactionButton.choosen = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java index e80a1529c..9469cf1e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -37,7 +37,7 @@ public class ActionBarMenuSubItem extends FrameLayout { private int itemHeight = 48; private final Theme.ResourcesProvider resourcesProvider; - Runnable openSwipeBackLayout; + public Runnable openSwipeBackLayout; public ActionBarMenuSubItem(Context context, boolean top, boolean bottom) { this(context, false, top, bottom); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index 99b549bbc..0592861fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -65,6 +65,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.EffectsTextView; import org.telegram.ui.Components.LayoutHelper; @@ -85,11 +86,12 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati public static final int ALERT_TYPE_LOADING = 2; public static final int ALERT_TYPE_SPINNER = 3; + private int customWidth = -1; private View customView; private View bottomView; private View aboveMessageView; private int customViewHeight = LayoutHelper.WRAP_CONTENT; - private TextView titleTextView; + private SpoilersTextView titleTextView; private TextView secondTitleTextView; private TextView subtitleTextView; private TextView messageTextView; @@ -343,6 +345,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati inLayout = true; int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); + + if (customWidth > 0) { + width = customWidth + backgroundPaddings.left + backgroundPaddings.right; + } + int maxContentHeight; int availableHeight = maxContentHeight = height - getPaddingTop() - getPaddingBottom(); int availableWidth = width - getPaddingLeft() - getPaddingRight(); @@ -598,7 +605,13 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati } containerView.setFitsSystemWindows(Build.VERSION.SDK_INT >= 21); if (setContent) { - setContentView(containerView); + if (customWidth > 0) { + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER; + setContentView(containerView, lp); + } else { + setContentView(containerView); + } } final boolean hasButtons = positiveButtonText != null || negativeButtonText != null || neutralButtonText != null; @@ -670,6 +683,8 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati containerView.addView(titleContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : 0, 24, 0, 24, 0)); titleTextView = new SpoilersTextView(getContext(), false); + NotificationCenter.listenEmojiLoading(titleTextView); + titleTextView.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; titleTextView.setText(title); titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); @@ -1546,6 +1561,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati return this; } + public Builder setWidth(int width) { + alertDialog.customWidth = width; + return this; + } + public Builder aboveMessageView(View view) { alertDialog.aboveMessageView = view; return this; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java index cbabb6538..a49530b7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java @@ -9,6 +9,7 @@ import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; import android.os.Build; +import android.util.Log; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.Gravity; @@ -25,6 +26,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; public class AlertDialogDecor extends AlertDialog { @@ -102,11 +104,8 @@ public class AlertDialogDecor extends AlertDialog { container.addView(dimView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); final FrameLayout contentWrapper = new FrameLayout(getContext()); - contentWrapper.addView(contentView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)); - - FrameLayout.LayoutParams containerParams = new FrameLayout.LayoutParams(params.width, FrameLayout.LayoutParams.WRAP_CONTENT); - containerParams.gravity = Gravity.CENTER; - container.addView(contentWrapper, containerParams); + contentWrapper.addView(contentView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); + container.addView(contentWrapper, new FrameLayout.LayoutParams(params.width, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); rootView = container; getDecorView().addView(rootView); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java index 029c6e58f..bfe7df8d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java @@ -16,7 +16,10 @@ import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.view.animation.DecelerateInterpolator; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; public class BackDrawable extends Drawable { @@ -111,11 +114,7 @@ public class BackDrawable extends Drawable { invalidateSelf(); } - int rD = rotated ? (int) ((Color.red(rotatedColor) - Color.red(color)) * currentRotation) : 0; - int rG = rotated ? (int) ((Color.green(rotatedColor) - Color.green(color)) * currentRotation) : 0; - int rB = rotated ? (int) ((Color.blue(rotatedColor) - Color.blue(color)) * currentRotation) : 0; - int c = Color.rgb(Color.red(color) + rD, Color.green(color) + rG, Color.blue(color) + rB); - paint.setColor(c); + paint.setColor(ColorUtils.blendARGB(color, rotatedColor, currentRotation)); canvas.save(); canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java new file mode 100644 index 000000000..4766642bc --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java @@ -0,0 +1,154 @@ +package org.telegram.ui.ActionBar; + +import android.graphics.Color; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.Utilities; + +// https://gist.github.com/dkaraush/65d19d61396f5f3cd8ba7d1b4b3c9432 +public class OKLCH { + + public static final double[] XYZtoLMS_M = new double[] { + 0.8190224379967030, 0.3619062600528904, -0.1288737815209879, + 0.0329836539323885, 0.9292868615863434, 0.0361446663506424, + 0.0481771893596242, 0.2642395317527308, 0.6335478284694309 + }; + public static final double[] LMStoXYZ_M = new double[] { + 1.2268798758459243, -0.5578149944602171, 0.2813910456659647, + -0.0405757452148008, 1.1122868032803170, -0.0717110580655164, + -0.0763729366746601, -0.4214933324022432, 1.5869240198367816 + }; + public static final double[] LMStoLab_M = new double[] { + 0.2104542683093140, 0.7936177747023054, -0.0040720430116193, + 1.9779985324311684, -2.4285922420485799, 0.4505937096174110, + 0.0259040424655478, 0.7827717124575296, -0.8086757549230774 + }; + public static final double[] LabtoLMS_M = new double[] { + 1., 0.3963377773761749, 0.2158037573099136, + 1., -0.1055613458156586, -0.0638541728258133, + 1., -0.0894841775298119, -1.2914855480194092, + }; + public static final double[] toXYZ_M = new double[] { + 0.41239079926595934, 0.357584339383878, 0.1804807884018343, + 0.21263900587151027, 0.715168678767756, 0.07219231536073371, + 0.01933081871559182, 0.11919477979462598, 0.9505321522496607 + }; + public static final double[] fromXYZ_M = new double[] { + 3.2409699419045226, -1.537383177570094, -0.4986107602930034, + -0.9692436362808796, 1.8759675015077202, 0.04155505740717559, + 0.05563007969699366, -0.20397695888897652, 1.0569715142428786 + }; + + public static double[] oklch2oklab(double[] lch) { + final double L = lch[0]; + final double C = lch[1]; + final double H = lch[2]; + return new double[] { + L, + Double.isNaN(H) ? 0 : C * Math.cos(H * Math.PI / 180), + Double.isNaN(H) ? 0 : C * Math.sin(H * Math.PI / 180) + }; + } + public static double[] oklab2oklch(double[] lab) { + final double L = lab[0]; + final double A = lab[1]; + final double B = lab[2]; + return new double[] { + L, + Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2)), + Math.abs(A) < 0.0002 && Math.abs(B) < 0.0002 ? Double.NaN : (((Math.atan2(B, A) * 180) / Math.PI % 360) + 360) % 360 + }; + } + + public static double[] rgb2srgbLinear(double[] rgb) { + double[] rgbLinear = new double[3]; + for (int i = 0; i < rgb.length; ++i) { + rgbLinear[i] = Math.abs(rgb[i]) <= 0.04045 ? + rgb[i] / 12.92 : + (rgb[i] < 0 ? -1 : 1) * (Math.pow((Math.abs(rgb[i]) + 0.055) / 1.055, 2.4)); + } + return rgbLinear; + } + public static double[] srgbLinear2rgb(double[] rgbLinear) { + double[] rgb = new double[3]; + for (int i = 0; i < rgbLinear.length; ++i) { + rgb[i] = Math.abs(rgbLinear[i]) > 0.0031308 ? + (rgbLinear[i] < 0 ? -1 : 1) * (1.055 * Math.pow(Math.abs(rgbLinear[i]), (1 / 2.4)) - 0.055) : + 12.92 * rgbLinear[i]; + } + return rgb; + } + + public static double[] oklab2xyz(double[] lab) { + final double[] LMS = multiply(LabtoLMS_M, lab); + for (int i = 0; i < LMS.length; ++i) { + LMS[i] = Math.pow(LMS[i], 3.0); + } + return multiply(LMStoXYZ_M, LMS); + } + public static double[] xyz2oklab(double[] xyz) { + final double[] LMSg = multiply(XYZtoLMS_M, xyz); + for (int i = 0; i < LMSg.length; ++i) { + LMSg[i] = Math.cbrt(LMSg[i]); + } + return multiply(LMStoLab_M, LMSg); + } + + public static double[] xyz2rgbLinear(double[] xyz) { + return multiply(fromXYZ_M, xyz); + } + public static double[] rgbLinear2xyz(double[] rgb) { + return multiply(toXYZ_M, rgb); + } + + public static double[] oklch2rgb(double[] lch) { + return srgbLinear2rgb(xyz2rgbLinear(oklab2xyz(oklch2oklab(lch)))); + } + + public static double[] rgb2oklch(double[] rgb) { + return oklab2oklch(xyz2oklab(rgbLinear2xyz(rgb2srgbLinear(rgb)))); + } + + public static double[] rgb(int color) { + return new double[] { + Color.red(color) / 255.0, + Color.green(color) / 255.0, + Color.blue(color) / 255.0 + }; + } + public static int rgb(double[] color) { + return Color.rgb( + (int) Math.round(Utilities.clamp(color[0], 1.0, 0.0) * 255.0), + (int) Math.round(Utilities.clamp(color[1], 1.0, 0.0) * 255.0), + (int) Math.round(Utilities.clamp(color[2], 1.0, 0.0) * 255.0) + ); + } + + // takes hue from `hueColor` color and applies to `baseColor` + public static int adapt(int baseColor, int hueColor) { + double[] hueoklch = rgb2oklch(rgb(hueColor)); + double[] oklch = rgb2oklch(rgb(baseColor)); + oklch[2] = hueoklch[2]; + if (Double.isNaN(hueoklch[2])) { + oklch[1] = hueoklch[1]; + } + return ColorUtils.setAlphaComponent(rgb(oklch2rgb(oklch)), Color.alpha(baseColor)); + } + + public static int adapt(int color, double c, double l) { + double[] oklch = rgb2oklch(rgb(color)); + oklch[0] = Utilities.clamp(oklch[0] + l, 1.0, 0.0); + oklch[1] = Utilities.clamp(oklch[1] + c, 1.0, 0.0); + return ColorUtils.setAlphaComponent(rgb(oklch2rgb(oklch)), Color.alpha(color)); + } + + private static double[] multiply(double[] mat3, double[] vec3) { + return new double[] { + mat3[0] * vec3[0] + mat3[1] * vec3[1] + mat3[2] * vec3[2], + mat3[3] * vec3[0] + mat3[4] * vec3[1] + mat3[5] * vec3[2], + mat3[6] * vec3[0] + mat3[7] * vec3[1] + mat3[8] * vec3[2] + }; + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index d5c5d570d..960e7915b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -3643,6 +3643,7 @@ public class Theme { public static final int key_chat_inBubbleShadow = colorsCount++; public static final int key_actionBarActionModeReaction = colorsCount++; + public static final int key_actionBarActionModeReactionText = colorsCount++; public static final int key_actionBarActionModeReactionDot = colorsCount++; //my messages bubbles @@ -3719,6 +3720,7 @@ public class Theme { public static final int key_chat_outLocationIcon = colorsCount++; public static final int key_chat_outContactBackground = colorsCount++; public static final int key_chat_outContactIcon = colorsCount++; + public static final int key_chat_outReactionButtonBackground = colorsCount++; public static final int myMessagesEndIndex = colorsCount; public static final int key_chat_outTextSelectionHighlight = colorsCount++; @@ -4101,7 +4103,6 @@ public class Theme { public static final int key_color_cyan = colorsCount++; public static final int[] keys_colors = {key_color_lightblue, key_color_blue, key_color_green, key_color_lightgreen, key_color_red, key_color_orange, key_color_yellow, key_color_purple, key_color_cyan}; - public static final int key_chat_outReactionButtonBackground = colorsCount++; public static final int key_chat_inReactionButtonBackground = colorsCount++; public static final int key_chat_outReactionButtonText = colorsCount++; public static final int key_chat_inReactionButtonText = colorsCount++; @@ -4395,6 +4396,7 @@ public class Theme { fallbackKeys.put(key_statisticChartLine_cyan, key_color_cyan); fallbackKeys.put(key_actionBarActionModeReaction, key_windowBackgroundGray); + fallbackKeys.put(key_actionBarActionModeReactionText, key_chat_inReactionButtonText); for (int i = 0; i < keys_avatar_background.length; i++) { themeAccentExclusionKeys.add(keys_avatar_background[i]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java index 2aa4323e7..25e14d08b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -138,8 +138,8 @@ public class ThemeColors { defaultColors[key_avatar_text] = 0xffffffff; - defaultColors[key_avatar_backgroundSaved] = 0xff69BFFA; - defaultColors[key_avatar_background2Saved] = 0xff3D9DE0; + defaultColors[key_avatar_backgroundSaved] = 0xff69BDF9; + defaultColors[key_avatar_background2Saved] = 0xff409FE1; defaultColors[key_avatar_backgroundArchived] = 0xffB8C2CC; defaultColors[key_avatar_backgroundArchivedHidden] = 0xff66bffa; defaultColors[key_avatar_backgroundRed] = 0xffFF845E; @@ -189,6 +189,7 @@ public class ThemeColors { defaultColors[key_actionBarDefaultSubmenuSeparator] = 0xfff5f5f5; defaultColors[key_actionBarActionModeDefaultSelector] = 0xffe2e2e2; defaultColors[key_actionBarActionModeReaction] = 0xfff0f0f0; + defaultColors[key_actionBarActionModeReactionText] = 0xff82868a; defaultColors[key_actionBarActionModeReactionDot] = 0xffc0c0c0; defaultColors[key_actionBarTabActiveText] = 0xffffffff; defaultColors[key_actionBarTabUnactiveText] = 0xffd5e8f7; @@ -957,6 +958,7 @@ public class ThemeColors { colorKeysMap.put(key_actionBarActionModeDefaultIcon, "actionBarActionModeDefaultIcon"); colorKeysMap.put(key_actionBarActionModeDefaultSelector, "actionBarActionModeDefaultSelector"); colorKeysMap.put(key_actionBarActionModeReaction, "actionBarActionModeReaction"); + colorKeysMap.put(key_actionBarActionModeReactionText, "actionBarActionModeReactionText"); colorKeysMap.put(key_actionBarActionModeReactionDot, "actionBarActionModeReactionDot"); colorKeysMap.put(key_actionBarDefaultTitle, "actionBarDefaultTitle"); colorKeysMap.put(key_actionBarDefaultSubtitle, "actionBarDefaultSubtitle"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 628a34cab..dea5bef42 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -471,7 +471,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); reqId = 0; } - if (TextUtils.isEmpty(query)) { + if (TextUtils.isEmpty(query) || delegate.getSearchForumDialogId() != 0) { filteredRecentQuery = null; searchResultMessages.clear(); searchForumResultMessages.clear(); @@ -1107,7 +1107,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (searchId != lastSearchId) { return; } - if (needMessagesSearch != 2 && dialogsType != DialogsActivity.DIALOGS_TYPE_GROUPS_ONLY && dialogsType != DialogsActivity.DIALOGS_TYPE_CHANNELS_ONLY) { + if (needMessagesSearch != 2 && dialogsType != DialogsActivity.DIALOGS_TYPE_GROUPS_ONLY && dialogsType != DialogsActivity.DIALOGS_TYPE_CHANNELS_ONLY && delegate.getSearchForumDialogId() == 0) { searchAdapterHelper.queryServerSearch( query, true, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java index a54538aaa..51f08c5ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java @@ -23,11 +23,14 @@ import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.HashSet; public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; + private HashSet messageIds = new HashSet<>(); private ArrayList searchResultMessages = new ArrayList<>(); + public int loadedCount; private int currentAccount = UserConfig.selectedAccount; private final Theme.ResourcesProvider resourcesProvider; @@ -39,7 +42,17 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter { @Override public void notifyDataSetChanged() { - searchResultMessages = MediaDataController.getInstance(currentAccount).getFoundMessageObjects(); + searchResultMessages.clear(); + messageIds.clear(); + ArrayList searchResults = MediaDataController.getInstance(currentAccount).getFoundMessageObjects(); + for (int i = 0; i < searchResults.size(); ++i) { + MessageObject m = searchResults.get(i); + if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) { + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + loadedCount = searchResultMessages.size(); super.notifyDataSetChanged(); } @@ -85,8 +98,26 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter { if (holder.getItemViewType() == 0) { DialogCell cell = (DialogCell) holder.itemView; cell.useSeparator = true; + cell.isSavedDialog = true; MessageObject messageObject = (MessageObject) getItem(position); - cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, true, false); + int date; + boolean useMe = false; + long did; + if (messageObject.getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) { + did = messageObject.getSavedDialogId(); + if (messageObject.messageOwner.fwd_from != null && (messageObject.messageOwner.fwd_from.date != 0 || messageObject.messageOwner.fwd_from.saved_date != 0)) { + date = messageObject.messageOwner.fwd_from.date; + if (date == 0) { + date = messageObject.messageOwner.fwd_from.saved_date; + } + } else { + date = messageObject.messageOwner.date; + } + } else { + did = messageObject.getDialogId(); + date = messageObject.messageOwner.date; + } + cell.setDialog(did, messageObject, date, useMe, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 170b4e95a..0a643c808 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -6487,7 +6487,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } videoPlayer.seekTo(playFrom); - videoPlayer.preparePlayer(uri, true); + videoPlayer.preparePlayer(uri, true, 1f); videoPlayer.play(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java index e3040fc65..3b06ec417 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java @@ -476,7 +476,13 @@ public class CalendarActivity extends BaseFragment implements NotificationCenter req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); } - req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.peer = getMessagesController().getInputPeer(dialogId); + if (topicId != 0) { + if (dialogId == getUserConfig().getClientUserId()) { + req.flags |= 4; + req.saved_peer_id = getMessagesController().getInputPeer(topicId); + } + } req.offset_id = lastId; Calendar calendar = Calendar.getInstance(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java index 73feedac3..cdc82f3be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java @@ -187,6 +187,14 @@ public class AboutLinkCell extends FrameLayout { setWillNotDraw(false); } + protected int processColor(int color) { + return color; + } + + public void updateColors() { + Theme.profile_aboutTextPaint.linkColor = processColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + } + @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); @@ -283,7 +291,7 @@ public class AboutLinkCell extends FrameLayout { canvas.translate(0, textY = AndroidUtilities.dp(8)); try { - Theme.profile_aboutTextPaint.linkColor = Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider); + Theme.profile_aboutTextPaint.linkColor = processColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); if (firstThreeLinesLayout == null || !shouldExpand) { if (textLayout != null) { textLayout.draw(canvas); @@ -461,7 +469,8 @@ public class AboutLinkCell extends FrameLayout { Spannable buffer = (Spannable) textLayout.getText(); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0 && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { - LinkSpanDrawable linkDrawable = new LinkSpanDrawable(link[0], parentFragment.getResourceProvider(), ex, ey); + LinkSpanDrawable linkDrawable = new LinkSpanDrawable(link[0], resourcesProvider, ex, ey); + linkDrawable.setColor(processColor(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider))); int start = buffer.getSpanStart(link[0]); int end = buffer.getSpanEnd(link[0]); LinkPath path = linkDrawable.obtainNewPath(); @@ -490,11 +499,12 @@ public class AboutLinkCell extends FrameLayout { links.removeLoading(currentLoading, true); } currentLoading = thisLoading = LinkSpanDrawable.LinkCollector.makeLoading(layout, pressedLink, yOffset); + final int color = processColor(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider)); thisLoading.setColors( - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), .8f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 1.3f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 1f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 4f) + Theme.multAlpha(color, .8f), + Theme.multAlpha(color, 1.3f), + Theme.multAlpha(color, 1f), + Theme.multAlpha(color, 4f) ); thisLoading.strokePaint.setStrokeWidth(AndroidUtilities.dpf2(1.25f)); links.addLoading(thisLoading); 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 90374361f..811ec9955 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -62,6 +62,7 @@ import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.LeadingMarginSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.Property; import android.util.SparseArray; import android.util.StateSet; @@ -383,11 +384,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - public void setScrimReaction(String scrimViewReaction) { + public void setScrimReaction(Integer scrimViewReaction) { reactionsLayoutInBubble.setScrimReaction(scrimViewReaction); } - public void drawScrimReaction(Canvas canvas, String scrimViewReaction) { + public void drawScrimReaction(Canvas canvas, Integer scrimViewReaction) { if ((currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) && !reactionsLayoutInBubble.isSmall) { reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress, scrimViewReaction); } @@ -656,6 +657,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressEmojiStatus() { } + + default boolean doNotShowLoadingReply(MessageObject msg) { + return msg != null && msg.getDialogId() == UserObject.REPLY_BOT; + } } private final static int DOCUMENT_ATTACH_TYPE_NONE = 0; @@ -757,7 +762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private static class InstantViewButton { private int type; - private int buttonWidth; + private float buttonWidth; private float textX; private StaticLayout layout; private final RectF rect = new RectF(); @@ -2512,7 +2517,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean checkInstantButtonMotionEvent(MotionEvent event) { - if (!currentMessageObject.isSponsored() && (!drawInstantView || currentMessageObject.type == MessageObject.TYPE_TEXT)) { + if (!currentMessageObject.isSponsored() && !currentMessageObject.isUnsupported() && (!drawInstantView || currentMessageObject.type == MessageObject.TYPE_TEXT)) { return false; } int x = (int) event.getX(); @@ -4862,7 +4867,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean pollChanged = false; if (!messageIdChanged && currentMessageObject != null) { + int oldStableId = messageObject.stableId; messageObject.copyStableParams(currentMessageObject); + if (currentMessageObject.isSavedFiltered && messageObject.isSavedFiltered) { + messageObject.stableId = oldStableId; + } } accessibilityText = null; if (drawCommentButton || useTranscribeButton || drawSideButton == 3 && !((hasDiscussion && messageObject.isLinkedToChat(linkedChatId) || isRepliesChat) && (currentPosition == null || currentPosition.siblingHeights == null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 || currentPosition.siblingHeights != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0))) { @@ -4924,7 +4933,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!groupChanged && groupedMessages != null) { MessageObject.GroupedMessagePosition newPosition; if (groupedMessages.messages.size() > 1) { - newPosition = currentMessagesGroup.positions.get(currentMessageObject); + newPosition = currentMessagesGroup.getPosition(currentMessageObject); } else { newPosition = null; } @@ -4948,7 +4957,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } widthBeforeNewTimeLine = -1; if (currentMessagesGroup != null && (currentMessagesGroup.posArray.size() > 1)) { - currentPosition = currentMessagesGroup.positions.get(currentMessageObject); + currentPosition = currentMessagesGroup.getPosition(currentMessageObject); if (currentPosition == null) { currentMessagesGroup = null; } @@ -5163,15 +5172,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageIdChanged || messageObject.reactionsChanged || wasPlayingRound != isPlayingRound) { messageObject.reactionsChanged = false; + boolean isTag = messageObject.messageOwner != null && messageObject.messageOwner.reactions != null && messageObject.messageOwner.reactions.reactions_as_tags; if (messageObject.shouldDrawReactions() && !messageObject.isExpiredStory() && (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0))) { boolean isSmall = !messageObject.shouldDrawReactionsInLayout(); if (currentPosition != null) { - reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + MessageObject primaryMessage = groupedMessages.findPrimaryMessageObject(); + if (!isTag) { + isTag = primaryMessage.messageOwner.reactions != null && primaryMessage.messageOwner.reactions.reactions_as_tags; + } + reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), isTag, resourcesProvider); } else { - reactionsLayoutInBubble.setMessage(messageObject, isSmall, resourcesProvider); + reactionsLayoutInBubble.setMessage(messageObject, isSmall, isTag, resourcesProvider); } } else { - reactionsLayoutInBubble.setMessage(null, false, resourcesProvider); + reactionsLayoutInBubble.setMessage(null, false, false, resourcesProvider); } } @@ -5381,7 +5395,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (!drawInstantView) { - if (messageObject.isSponsored()) { + if (messageObject.isUnsupported()) { + drawInstantView = true; + drawInstantViewType = 21; + } else if (messageObject.isSponsored()) { drawInstantView = true; hasLinkPreview = true; instantViewButtonText = messageObject.sponsoredButtonText; @@ -5658,7 +5675,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewMaxWidth = getParentWidth() - AndroidUtilities.dp(80 + (drawAvatar ? 52 : 0)); } if (drawSideButton != 0) { - linkPreviewMaxWidth -= AndroidUtilities.dp(20); + linkPreviewMaxWidth -= AndroidUtilities.dp(currentMessageObject.isSaved && currentMessageObject.isOutOwner() ? 25 : 20); } int site_name_additionalWidth = 0; CharSequence site_name; @@ -6624,6 +6641,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate blurredPhotoImage.getBitmap().recycle(); blurredPhotoImage.setImageBitmap((Bitmap) null); } + + if (messageObject.isUnsupported()) { + createInstantViewButton(); + } } } else if (messageObject.type == MessageObject.TYPE_PHONE_CALL) { createSelectorDrawable(0); @@ -7271,30 +7292,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (!reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) { if (!drawPhotoImage) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(2); + reactionsLayoutInBubble.positionOffsetY += dp(2); } - if (captionLayout != null && currentPosition != null && currentMessagesGroup != null && currentMessagesGroup.isDocuments) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } else if (!drawPhotoImage && !TextUtils.isEmpty(messageObject.caption) && ((docTitleLayout != null && docTitleLayout.getLineCount() > 1) || currentMessageObject.hasValidReplyMessageObject()) && !currentMessageObject.isForwarded()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } else if (!drawPhotoImage && !TextUtils.isEmpty(messageObject.caption) && !currentMessageObject.isOutOwner()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } - reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8); + reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + dp(!drawPhotoImage || captionLayout == null ? 8 : 0); measureTime(messageObject); if (drawPhotoImage && captionLayout == null) { - reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(8); - } - if (!drawPhotoImage && captionLayout != null && currentMessageObject != null && currentMessageObject.isOutOwner() && currentMessageObject.isDocument() && currentMessagesGroup == null && !currentMessageObject.isForwarded() && !currentMessageObject.isReply()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); + reactionsLayoutInBubble.totalHeight += dp(8); } - int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - AndroidUtilities.dp(31); + int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - dp(42); if (timeLeft < timeWidth) { - reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(12); - reactionsLayoutInBubble.positionOffsetY -= AndroidUtilities.dp(12); + reactionsLayoutInBubble.totalHeight += dp(captionLayout == null ? 15 : 12); + reactionsLayoutInBubble.positionOffsetY -= dp(15); } additionHeight += reactionsLayoutInBubble.totalHeight; } @@ -8387,7 +8398,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate invalidate(); } - if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0 && !messageObject.isExpiredStory()) { + if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0 && !messageObject.isExpiredStory() && !messageObject.isUnsupported()) { int addCaptionLayoutWidth = 0; if (!messageObject.isRestrictedMessage && captionLayout == null && (messageObject.caption != null || messageObject.isVoiceTranscriptionOpen())) { currentCaption = messageObject.isVoiceTranscriptionOpen() ? messageObject.getVoiceTranscription() : messageObject.caption; @@ -9317,6 +9328,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } useTranscribeButton = ( currentMessageObject != null && + !currentMessageObject.isRepostPreview && (!currentMessageObject.isOutOwner() || currentMessageObject.isSent()) && ( UserConfig.getInstance(currentAccount).isPremium() @@ -9566,6 +9578,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int newLineForTimeDp = 14; + if (currentMessageObject.isUnsupported()) { + newLineForTime = true; + } if ( currentMessageObject.hasCodeAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) || currentMessageObject.hasQuoteAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) @@ -9858,7 +9873,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector || who == nameLayoutSelector || who == replySelector; + return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector || who == nameLayoutSelector || who == replySelector || reactionsLayoutInBubble != null && reactionsLayoutInBubble.verifyDrawable(who); } @Override @@ -9941,7 +9956,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return; } int color; - if (psaHintPressed) { + if (currentMessageObject.isUnsupported()) { + color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewInstantText : Theme.key_chat_inPreviewInstantText); + } else if (psaHintPressed) { color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outViews : Theme.key_chat_inViews); } else if (linkLine != null) { color = linkLine.getColor(); @@ -10088,6 +10105,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork); } else if (drawInstantViewType == 20) { str = LocaleController.getString(R.string.OpenGift); + } else if (drawInstantViewType == 21) { + str = LocaleController.getString(R.string.AppUpdate); } else { str = LocaleController.getString(R.string.InstantView); } @@ -10147,7 +10166,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (needRecreate) { drawnContactButtonsFlag = 0; int mWidth = (backgroundWidth - AndroidUtilities.dp(10 + 24 + 10 + 31)) / buttonsCount; - int parentWidth = (backgroundWidth - AndroidUtilities.dp(37)) / buttonsCount; + float parentWidth = (backgroundWidth - AndroidUtilities.dpf2(37)) / buttonsCount; if (contactButtons == null) { contactButtons = new ArrayList<>(buttonsCount); @@ -10177,7 +10196,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - private InstantViewButton createInstantViewButton(int type, String str, int availableWidth, int parentWidth) { + private InstantViewButton createInstantViewButton(int type, String str, int availableWidth, float parentWidth) { InstantViewButton instantViewButton = new InstantViewButton(); instantViewButton.type = type; instantViewButton.layout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, availableWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, availableWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); @@ -11616,7 +11635,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasNewLineForTime && !(drawForwardedName && hasLinkPreview && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO)) { reactionsLayoutInBubble.y -= AndroidUtilities.dp(16); } - if (captionLayout != null && ((currentMessageObject.type != MessageObject.TYPE_VOICE && !(currentMessageObject.isOut() && drawForwardedName && !drawPhotoImage) && !(currentMessageObject.type == MessageObject.TYPE_FILE && drawPhotoImage)) || (currentPosition != null && currentMessagesGroup != null))) { + if (currentMessageObject.type != MessageObject.TYPE_FILE && (captionLayout != null && ((currentMessageObject.type != MessageObject.TYPE_VOICE && !(currentMessageObject.isOut() && drawForwardedName && !drawPhotoImage)) || (currentPosition != null && currentMessagesGroup != null)))) { reactionsLayoutInBubble.y -= AndroidUtilities.dp(14); } reactionsLayoutInBubble.y += reactionsLayoutInBubble.positionOffsetY; @@ -11743,7 +11762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public void drawLinkPreview(Canvas canvas, float alpha) { - if (!currentMessageObject.isSponsored() && !hasLinkPreview && !hasGamePreview && !hasInvoicePreview) { + if (!currentMessageObject.isSponsored() && !currentMessageObject.isUnsupported() && !hasLinkPreview && !hasGamePreview && !hasInvoicePreview) { return; } int restoreCount = canvas.getSaveCount(); @@ -11807,7 +11826,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean restore = false; boolean drawInstantButtonInside = false; boolean loading = delegate != null && delegate.isProgressLoading(this, ChatActivity.PROGRESS_INSTANT); - if (!hasInvoicePreview && !currentMessageObject.isGiveawayOrGiveawayResults()) { + if (!hasInvoicePreview && !currentMessageObject.isGiveawayOrGiveawayResults() && !currentMessageObject.isUnsupported()) { drawInstantButtonInside = true; if (linkPreviewBounce == null) { @@ -12223,7 +12242,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { int color = getThemedColor(Theme.key_chat_inPreviewInstantText); - if (linkLine != null) { + if (linkLine != null && !currentMessageObject.isUnsupported()) { color = linkLine.getColor(); } if (this.instantDrawable == null) { @@ -12274,7 +12293,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); } } else { - int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(10); + int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(currentMessageObject.isUnsupported() ? -5 : 10); if (instantButtonLoading != null && !loading && !instantButtonLoading.isDisappeared() && !instantButtonLoading.isDisappearing()) { instantButtonLoading.disappear(); } @@ -12420,17 +12439,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.drawRect(contactRect.left + AndroidUtilities.dp(3 + 7), instantY + AndroidUtilities.dp(2), contactRect.right - AndroidUtilities.dp(7), instantY + AndroidUtilities.dp(2) + Math.max(1, AndroidUtilities.dp(0.66f)), Theme.chat_instantViewPaint); Theme.chat_instantViewPaint.setAlpha(wasAlpha); instantY += AndroidUtilities.dp(2); - textX += AndroidUtilities.dp(3); + float instantButtonLeft = textX + AndroidUtilities.dp(3); boolean needCreateSelectorDrawable = contactButtons != null && contactButtons.size() > 1; int rippleColor = contactLine.getBackgroundColor(); for (int i = 0; i < contactButtons.size(); i++) { InstantViewButton instantViewButton = contactButtons.get(i); - instantViewButton.rect.set(textX, instantY, textX + instantViewButton.buttonWidth, instantY + AndroidUtilities.dp(36)); + float right = Math.min(instantButtonLeft + instantViewButton.buttonWidth, contactRect.right); + instantViewButton.rect.set(instantButtonLeft, instantY, right, instantY + AndroidUtilities.dp(36)); if (needCreateSelectorDrawable && instantViewButton.selectorDrawable == null) { instantViewButton.selectorDrawable = Theme.createRadSelectorDrawable(linkPreviewSelectorColor = rippleColor, 0, 0, i == (contactButtons.size() - 1) ? rad : 0, 0); } if (instantViewButton.selectorDrawable != null) { - instantViewButton.selectorDrawable.setBounds(textX, instantY, textX + instantViewButton.buttonWidth, instantY + AndroidUtilities.dp(36)); + instantViewButton.selectorDrawable.setBounds((int) instantButtonLeft, instantY, (int) right, instantY + AndroidUtilities.dp(36)); instantViewButton.selectorDrawable.draw(canvas); } float buttonScale = 1f; @@ -12447,14 +12467,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (instantViewButton.layout != null) { canvas.save(); - canvas.translate(textX + instantViewButton.textX, instantY + AndroidUtilities.dp(10.5f)); + canvas.translate(instantButtonLeft + instantViewButton.textX, instantY + AndroidUtilities.dp(10.5f)); instantViewButton.layout.draw(canvas); canvas.restore(); } if (needButtonScale) { canvas.restore(); } - textX += instantViewButton.buttonWidth; + instantButtonLeft += instantViewButton.buttonWidth; } } if (needContactViewScale) { @@ -12858,7 +12878,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate restore = canvas.saveLayerAlpha(rect, (int) (alpha * 255), Canvas.ALL_SAVE_FLAG); } } - int spoilersColor = currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : Theme.chat_msgTextPaint.getColor(); + int spoilersColor = currentMessageObject.isOutOwner() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : Theme.chat_msgTextPaint.getColor(); if (quoteHighlight != null && currentMessagesGroup == null) { Theme.MessageDrawable backgroundDrawable = currentBackgroundDrawable; if (backgroundDrawable != null) { @@ -13157,17 +13177,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { int maxWidth; if (AndroidUtilities.isTablet()) { - if (needDrawAvatar()) { - maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(42); - } else { - maxWidth = AndroidUtilities.getMinTabletSide(); - } + maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(needDrawAvatar() ? 42 : 0); } else { - if (needDrawAvatar()) { - maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y) - AndroidUtilities.dp(42); - } else { - maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y); - } + maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y) - AndroidUtilities.dp(needDrawAvatar() ? 42 : 0); + } + if (currentMessageObject != null && currentMessageObject.isSaved && currentMessageObject.isOutOwner() && checkNeedDrawShareButton(currentMessageObject)) { + maxWidth -= dp(25); } if (isPlayingRound && (currentMessageObject == null || !currentMessageObject.isVoiceTranscriptionOpen())) { int backgroundWidthLocal = backgroundWidth - (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize); @@ -13195,7 +13210,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) { return Math.max(currentMessageObject.textWidth, (int) ((AndroidUtilities.displaySize.x - AndroidUtilities.dp(52) - (isAvatarVisible ? AndroidUtilities.dp(48) : 0)) * .5f)); } else { - return backgroundWidth - AndroidUtilities.dp(mediaBackground ? 22 : 31); + int width = backgroundWidth; + if (currentMessageObject != null && currentMessageObject.isSaved && currentMessageObject.isOutOwner() && checkNeedDrawShareButton(currentMessageObject)) { + width -= dp(25); + } + width -= dp(mediaBackground ? 22 : 31); + return width; } } @@ -14254,6 +14274,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate timeString = LocaleController.formatSmallDateChat(messageObject.messageOwner.date) + ", " + LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); } else if (edited) { timeString = LocaleController.getString("EditedMessage", R.string.EditedMessage) + " " + LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); + } else if (currentMessageObject.isSaved && currentMessageObject.messageOwner.fwd_from != null && (currentMessageObject.messageOwner.fwd_from.date != 0 || currentMessageObject.messageOwner.fwd_from.saved_date != 0)) { + int date = currentMessageObject.messageOwner.fwd_from.date; + if (date == 0) { + date = currentMessageObject.messageOwner.fwd_from.saved_date; + } + timeString = LocaleController.formatSeenDate(date); } else { timeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); } @@ -14368,7 +14394,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (currentMessagesGroup != null && currentPosition != null) { final boolean last = (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & (messageObject.isOutOwner() ? MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_RIGHT)) != 0; - if ((!currentMessagesGroup.reversed && !currentMessagesGroup.isDocuments && !last || currentMessagesGroup.reversed && !last)) { + if (!currentMessagesGroup.isDocuments && !last) { return false; } } @@ -14735,7 +14761,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate topicButton = null; } - if (!messageObject.isGiveawayResults() && (!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.story_id != 0 || !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) || messageObject.messageOwner.reply_to.reply_from != null))) { + if ((!messageObject.isGiveawayResults() && (!isThreadChat || isSavedChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.story_id != 0 || !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) || messageObject.messageOwner.reply_to.reply_from != null))) && !messageObject.isRepostPreview) { if (currentPosition == null || currentPosition.minY == 0) { if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO || messageObject.type == MessageObject.TYPE_EMOJIS) { namesOffset += AndroidUtilities.dp(20) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); @@ -14753,7 +14779,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!messageObject.shouldDrawWithoutBackground()) { maxWidth -= AndroidUtilities.dp(messageObject.isOutOwner() ? 20 : 10); if (messageObject.type != MessageObject.TYPE_TEXT || messageObject.needDrawShareButton()) { - maxWidth -= AndroidUtilities.dp(10); + maxWidth -= AndroidUtilities.dp(messageObject.isSaved && messageObject.isOutOwner() ? 35 : 10); } } else if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { maxWidth += AndroidUtilities.dp(13); @@ -14785,7 +14811,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate stringFinalText = StoriesUtilities.createReplyStoryString(); maxWidth -= AndroidUtilities.dp(16) + (textPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); } - } else if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || hasReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) { + } else if ((!isThreadChat || isSavedChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || hasReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) { lastReplyMessage = messageObject.replyMessageObject == null ? null : messageObject.replyMessageObject.messageOwner; int cacheType = 1; int size = 0; @@ -15050,7 +15076,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyTextWidth -= sz; maxWidth += sz; } - if (changed || !isReplyQuote && (currentMessageObject.shouldDrawWithoutBackground() || Build.VERSION.SDK_INT < Build.VERSION_CODES.M)) { + if (changed || !isReplyQuote) { stringFinalText = TextUtils.ellipsize(sb, textPaint, maxWidth, TextUtils.TruncateAt.END); } else { stringFinalText = sb; @@ -15103,8 +15129,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate FileLog.e(e); } } - } else if (!isThreadChat && messageObject.getReplyMsgId() != 0 && !messageObject.isGiveawayResults()) { - if (!(messageObject.replyMessageObject != null && (messageObject.replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || messageObject.replyMessageObject.messageOwner != null && messageObject.replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) && messageObject.getDialogId() != UserObject.REPLY_BOT) { + } else if (!isThreadChat && messageObject.getReplyMsgId() != 0 && !messageObject.isGiveawayResults() && !messageObject.isRepostPreview) { + if (!(messageObject.replyMessageObject != null && (messageObject.replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || messageObject.replyMessageObject.messageOwner != null && messageObject.replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) && (delegate == null || delegate.doNotShowLoadingReply(messageObject))) { if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO) { namesOffset += AndroidUtilities.dp(14 + 4) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); if (messageObject.type != MessageObject.TYPE_TEXT) { @@ -16432,8 +16458,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } - if (drawSideButton != 4 && sideStartY < (layoutHeight - AndroidUtilities.dp(32)) / 2f) { - sideStartY = (layoutHeight - AndroidUtilities.dp(32)) / 2f; + if (drawSideButton != 4) { + float sideMin = (layoutHeight + transitionParams.deltaBottom - AndroidUtilities.dp(32)) / 2f; + if (sideStartY < sideMin) { + sideStartY = sideMin; + } } if (!currentMessageObject.isOutOwner() && isRoundVideo && !hasLinkPreview) { float offsetSize = isAvatarVisible ? ((AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f) : AndroidUtilities.dp(50); @@ -16689,7 +16718,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyForwardAlpha = 0; } } - if (drawNameLayout && nameLayout != null) { + if ((drawNameLayout || transitionParams.animateDrawNameLayout) && nameLayout != null) { + float nameAlpha = !transitionParams.animateDrawNameLayout ? 1f : (drawNameLayout ? transitionParams.animateChangeProgress : 1f - transitionParams.animateChangeProgress); canvas.save(); int oldAlpha; @@ -16813,6 +16843,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4)), (int) (nameY + nameLayout.getHeight() + dp(1.33f)) ); + nameLayoutSelector.setAlpha((int) (0xFF * nameAlpha)); nameLayoutSelector.draw(canvas); if (currentNameStatus != null) { @@ -16828,12 +16859,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4 + 12 + 4 + 4)), (int) (nameY + nameLayout.getHeight() + dp(1.33f + 2)) ); + nameStatusSelector.setAlpha((int) (0xFF * nameAlpha)); nameStatusSelector.draw(canvas); } } canvas.translate(nx, nameY); + oldAlpha = Theme.chat_namePaint.getAlpha(); + Theme.chat_namePaint.setAlpha((int) (oldAlpha * nameAlpha)); nameLayout.draw(canvas); + Theme.chat_namePaint.setAlpha(oldAlpha); canvas.restore(); float end; if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { @@ -17379,7 +17414,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); } int spoilersColor; - if (currentMessageObject != null && currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount)) { + if (currentMessageObject != null && currentMessageObject.isOutOwner() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount)) { spoilersColor = getThemedColor(Theme.key_chat_outTimeText); } else { spoilersColor = Theme.chat_replyTextPaint.getColor(); @@ -20324,7 +20359,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int h = 0; for (int i = 0; i < groupedMessages.messages.size(); i++) { MessageObject o = groupedMessages.messages.get(i); - MessageObject.GroupedMessagePosition position = groupedMessages.positions.get(o); + MessageObject.GroupedMessagePosition position = groupedMessages.getPosition(o); if (position != null && (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { setMessageContent(o, groupedMessages, false, false); if (withCaption && !TextUtils.isEmpty(currentCaption)) { @@ -20792,7 +20827,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawInstantView && !instantButtonRect.isEmpty()) { info.addChild(ChatMessageCell.this, INSTANT_VIEW); } - if (drawContact && !contactRect.isEmpty()) { + if (drawContact && contactRect != null && !contactRect.isEmpty()) { info.addChild(ChatMessageCell.this, CONTACT); if (contactButtons != null && contactButtons.size() > 1) { for (InstantViewButton instantViewButton : contactButtons) { @@ -21608,6 +21643,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean animateRecommendationsExpanded; public boolean animateFromRecommendationsExpanded; + public boolean lastDrawNameLayout; + public boolean animateDrawNameLayout; + public void recordDrawingState() { wasDraw = true; lastDrawingImageX = photoImage.getImageX(); @@ -21701,6 +21739,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { lastDrawReplyY = 0; } + + lastDrawNameLayout = drawNameLayout; } public void recordDrawingStatePreview() { @@ -21748,6 +21788,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, animatedEmojiStack, currentMessageObject.textLayoutBlocks); } } + animateDrawNameLayout = false; + if (drawNameLayout != lastDrawNameLayout) { + animateDrawNameLayout = true; + changed = true; + } if (replyTextLayout != lastDrawnReplyTextLayout) { CharSequence newText = replyTextLayout != null ? replyTextLayout.getText() : null; CharSequence oldText = lastDrawnReplyTextLayout != null ? lastDrawnReplyTextLayout.getText() : null; @@ -22056,6 +22101,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animateRadius = false; animateChangeProgress = 1f; animateMessageText = false; + animateDrawNameLayout = false; animateOutTextBlocks = null; animateEditedLayout = null; animateTimeLayout = null; @@ -22209,4 +22255,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate protected boolean drawPhotoImage(Canvas canvas) { return photoImage.draw(canvas); } + + public boolean areTags() { + MessageObject msg = getPrimaryMessageObject(); + if (msg == null) return false; + if (msg.messageOwner == null) return false; + if (msg.messageOwner.reactions == null) return false; + return msg.messageOwner.reactions.reactions_as_tags; + } } 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 c52f1c644..436877697 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -171,6 +171,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private Paint timerPaint2; SharedResources sharedResources; public boolean isSavedDialog; + public boolean isSavedDialogCell; public final StoriesUtilities.AvatarStoryParams storyParams = new StoriesUtilities.AvatarStoryParams(false) { @Override @@ -331,7 +332,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private int currentDialogFolderId; private int currentDialogFolderDialogsCount; private int currentEditDate; - private boolean isDialogCell; + public boolean isDialogCell; private int lastMessageDate; private int unreadCount; private boolean markUnread; @@ -950,6 +951,11 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { + Theme.dialogs_namePaint[0].setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_nameEncryptedPaint[0].setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_messagePaint[0].setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_messagePrintingPaint[0].setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_namePaint[1].setTextSize(AndroidUtilities.dp(16)); Theme.dialogs_nameEncryptedPaint[1].setTextSize(AndroidUtilities.dp(16)); Theme.dialogs_messagePaint[1].setTextSize(AndroidUtilities.dp(15)); @@ -1226,7 +1232,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (draftMessage != null && TextUtils.isEmpty(draftMessage.message)) { draftMessage = null; } - } else if (isDialogCell) { + } else if (isDialogCell || isSavedDialogCell) { draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0); } else { draftMessage = null; @@ -1425,9 +1431,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } else { needEmoji = true; updateMessageThumbs(); - if (chat != null && chat.id > 0 && fromChat == null && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message)) { - messageNameString = getMessageNameString(); - if (chat.forum && !isTopic && !useFromUserAsAvatar) { + String triedMessageName = null; + if (!isSavedDialog && user != null && user.self && !message.isOutOwner()) { + triedMessageName = getMessageNameString(); + } + if (isSavedDialog && user != null && !user.self && message != null && message.isOutOwner() || triedMessageName != null || chat != null && chat.id > 0 && fromChat == null && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message)) { + messageNameString = triedMessageName != null ? triedMessageName : getMessageNameString(); + if (chat != null && chat.forum && !isTopic && !useFromUserAsAvatar) { CharSequence topicName = MessagesController.getInstance(currentAccount).getTopicsController().getTopicIconName(chat, message, currentMessagePaint); if (!TextUtils.isEmpty(topicName)) { SpannableStringBuilder arrowSpan = new SpannableStringBuilder("-"); @@ -2205,7 +2215,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (messageString instanceof Spannable) { Spannable messageStringSpannable = (Spannable) messageString; for (Object span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), Object.class)) { - if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || span instanceof TypefaceSpan || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { + if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || !isFolderCell() && span instanceof TypefaceSpan || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { messageStringSpannable.removeSpan(span); } } @@ -3041,7 +3051,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava reactionsMentionsAnimator.start(); } - avatarImage.setRoundRadius(chat != null && chat.forum && currentDialogFolderId == 0 && !useFromUserAsAvatar ? AndroidUtilities.dp(16) : AndroidUtilities.dp(28)); + avatarImage.setRoundRadius(chat != null && chat.forum && currentDialogFolderId == 0 && !useFromUserAsAvatar || !isSavedDialog && user != null && user.self && MessagesController.getInstance(currentAccount).savedViewAsChats ? dp(16) : dp(28)); } if (!isTopic && (getMeasuredWidth() != 0 || getMeasuredHeight() != 0)) { rebuildLayout = true; @@ -4797,6 +4807,24 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava TLRPC.User fromUser = null; TLRPC.Chat fromChat = null; long fromId = message.getFromChatId(); + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + if (!isSavedDialog && currentDialogId == selfId) { + long savedDialogId = message.getSavedDialogId(); + if (savedDialogId == selfId) { + return null; + } else if (savedDialogId != UserObject.ANONYMOUS) { + if (message.messageOwner != null && message.messageOwner.fwd_from != null) { + long fwdId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.saved_from_id); + if (fwdId == 0) { + fwdId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.from_id); + } + if (fwdId > 0 && fwdId != savedDialogId) { + return null; + } + } + fromId = savedDialogId; + } + } if (isSavedDialog && message.messageOwner != null && message.messageOwner.fwd_from != null) { fromId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.saved_from_id); if (fromId == 0) { @@ -4809,7 +4837,14 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava fromChat = MessagesController.getInstance(currentAccount).getChat(-fromId); } - if (message.isOutOwner()) { + if (currentDialogId == selfId) { + if (fromUser != null) { + return UserObject.getFirstName(fromUser).replace("\n", ""); + } else if (fromChat != null) { + return fromChat.title.replace("\n", ""); + } + return null; + } else if (message.isOutOwner()) { return LocaleController.getString("FromYou", R.string.FromYou); } else if (!isSavedDialog && message != null && message.messageOwner != null && message.messageOwner.from_id instanceof TLRPC.TL_peerUser && (user = MessagesController.getInstance(currentAccount).getUser(message.messageOwner.from_id.user_id)) != null) { return UserObject.getFirstName(user).replace("\n", ""); @@ -4827,7 +4862,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } else if (fromChat != null && fromChat.title != null) { return fromChat.title.replace("\n", ""); - }else { + } else { return "DELETED"; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java index c32605d25..3e895fc02 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java @@ -14,6 +14,7 @@ import android.text.TextUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -36,7 +37,17 @@ public class ExpiredStoryView { public void measure(ChatMessageCell parent) { CharSequence title = StoriesUtilities.createExpiredStoryString(); - TLRPC.TL_messageMediaStory mediaStory = (TLRPC.TL_messageMediaStory) parent.getMessageObject().messageOwner.media; + MessageObject messageObject = parent.getMessageObject(); + TLRPC.TL_messageMediaStory mediaStory; + if (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaStory) { + mediaStory = (TLRPC.TL_messageMediaStory) messageObject.messageOwner.media; + } else { + verticalPadding = AndroidUtilities.dp(4); + horizontalPadding = AndroidUtilities.dp(12); + height = 0; + width = 0; + return; + } TLRPC.User user = MessagesController.getInstance(parent.currentAccount).getUser(mediaStory.user_id); String fromName = user == null ? "DELETED" : user.first_name; int forwardedNameWidth; @@ -119,9 +130,13 @@ public class ExpiredStoryView { canvas.save(); canvas.translate(textX, textY); - titleLayout.draw(canvas); - canvas.translate(0, titleLayout.getHeight() + AndroidUtilities.dp(2)); - subtitleLayout.draw(canvas); + if (titleLayout != null) { + titleLayout.draw(canvas); + canvas.translate(0, titleLayout.getHeight() + AndroidUtilities.dp(2)); + } + if (subtitleLayout != null) { + subtitleLayout.draw(canvas); + } canvas.restore(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java index 2c4d6a7c5..92881b60f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -399,8 +399,13 @@ public class StickerSetCell extends FrameLayout { } else { sideButtons.setVisibility(checked ? VISIBLE : INVISIBLE); if (!checked) { + sideButtons.setAlpha(0f); sideButtons.setScaleX(0.1f); sideButtons.setScaleY(0.1f); + } else { + sideButtons.setAlpha(1f); + sideButtons.setScaleX(1f); + sideButtons.setScaleY(1f); } } } else if (option == 3) { @@ -424,8 +429,13 @@ public class StickerSetCell extends FrameLayout { } else { optionsButton.setVisibility(checked ? VISIBLE : INVISIBLE); if (!checked) { + optionsButton.setAlpha(0f); optionsButton.setScaleX(0.1f); optionsButton.setScaleY(0.1f); + } else { + optionsButton.setAlpha(1f); + optionsButton.setScaleX(1f); + optionsButton.setScaleY(1f); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 6dbc2f11b..f6a957bc3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -268,7 +268,7 @@ public class TextCell extends FrameLayout { int textKey = textView.getTag() instanceof Integer ? (int) textView.getTag() : Theme.key_windowBackgroundWhiteBlackText; textView.setTextColor(processColor(Theme.getColor(textKey, resourcesProvider))); if (imageView.getTag() instanceof Integer) { - imageView.setColorFilter(new PorterDuffColorFilter(processColor(Theme.getColor((int) imageView.getTag(), resourcesProvider)), PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor((int) imageView.getTag(), resourcesProvider), PorterDuff.Mode.MULTIPLY)); } subtitleView.setTextColor(processColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider))); valueTextView.setTextColor(processColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText, resourcesProvider))); @@ -279,7 +279,7 @@ public class TextCell extends FrameLayout { textView.setTextColor(processColor(Theme.getColor(text, resourcesProvider))); textView.setTag(text); if (icon >= 0) { - imageView.setColorFilter(new PorterDuffColorFilter(processColor(Theme.getColor(icon, resourcesProvider)), PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(icon, resourcesProvider), PorterDuff.Mode.MULTIPLY)); imageView.setTag(icon); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index c33fffe3c..6f3000f7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -241,6 +241,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -291,9 +292,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean chatActivityEnterViewAnimateBeforeSending; private ActionBarMenuItem.Item timeItem2; private ActionBarMenu.LazyItem attachItem; + private ActionBarMenuItem.Item savedChatsItem, savedChatsGap;; private ActionBarMenuItem headerItem; private ActionBarMenu.LazyItem editTextItem; - private ActionBarMenuItem searchItem; + protected ActionBarMenuItem searchItem; private ActionBarMenuItem.Item translateItem; private ActionBarMenuItem searchIconItem; private ActionBarMenu.LazyItem audioCallIconItem; @@ -339,6 +341,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ActionBarMenuItem.Item muteItemGap; private ChatNotificationsPopupWrapper chatNotificationsPopupWrapper; private float pagedownButtonEnterProgress; + private float searchUpDownEnterProgress; private float mentionsButtonEnterProgress; private float reactionsMentionButtonEnterProgress; private FrameLayout pagedownButton; @@ -354,8 +357,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Bulletin messageSeenPrivacyBulletin; TextView webBotTitle; public SearchTagsList actionBarSearchTags; + private FrameLayout searchUpButton; + private ImageView searchUpButtonArrow; + private FrameLayout searchDownButton; + private ImageView searchDownButtonArrow; private HintView2 savedMessagesHint; + private HintView2 savedMessagesSearchHint; + private HintView2 savedMessagesTagHint; private int reactionsMentionCount; private FrameLayout reactionsMentiondownButton; @@ -399,7 +408,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private HintView gifHintTextView; private HintView emojiHintTextView; private HintView mediaBanTooltip; - private HintView searchAsListHint; private HintView scheduledOrNoSoundHint; private boolean scheduledOrNoSoundHintShown; private HintView scheduledHint; @@ -443,12 +451,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet alertViewAnimator; private final int searchContainerHeight = 51; private BlurredFrameLayout searchContainer; - private View searchAsListTogglerView; private ImageView searchCalendarButton; private ImageView searchUserButton; - private ImageView searchUpButton; - private ImageView searchDownButton; - private SearchCounterView searchCountText; + private AnimatedTextView searchCountText; + private AnimatedTextView searchExpandList; private AnimatedTextView searchOtherButton; private ChatActionCell floatingDateView; private ChatActionCell infoTopView; @@ -464,7 +470,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean searchingForUser; private TLRPC.User searchingUserMessages; private TLRPC.Chat searchingChatMessages; - private ReactionsLayoutInBubble.VisibleReaction searchingReaction; + public ReactionsLayoutInBubble.VisibleReaction searchingReaction; + public ReactionsLayoutInBubble.VisibleReaction getFilterTag() { + return chatAdapter != null && chatAdapter.isFiltered ? searchingReaction : null; + } + public String getFilterQuery() { + return chatAdapter != null && chatAdapter.isFiltered ? searchingQuery : null; + } + public boolean isFiltered() { + return chatAdapter != null && chatAdapter.isFiltered; + } + public ArrayList getFilteredMessages() { + return chatAdapter != null ? chatAdapter.filteredMessages : null; + } + private boolean searchingFiltered; + private boolean searching; + private String searchingQuery; private UndoView undoView; private UndoView topUndoView; private Bulletin pinBulletin; @@ -476,6 +497,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessageObject hintMessageObject; private int hintMessageType; + private MessageObject hint2MessageObject; private RecyclerListView messagesSearchListView; private MessagesSearchAdapter messagesSearchAdapter; @@ -547,6 +569,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean pinnedEndReached; private ValueAnimator pagedownButtonAnimation; + private ValueAnimator searchUpButtonAnimation; private ValueAnimator mentiondownButtonAnimation; private ValueAnimator reactionsMentionButtonAnimation; private AnimatorSet replyButtonAnimation; @@ -554,7 +577,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet forwardButtonAnimation; SparseIntArray dateObjectsStableIds = new SparseIntArray(); - private static int lastStableId = 10; + public static int lastStableId = 10; private boolean openSearchKeyboard; @@ -647,6 +670,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private SparseArray repliesMessagesDict = new SparseArray<>(); private SparseArray> replyMessageOwners = new SparseArray<>(); private HashMap> messagesByDays = new HashMap<>(); + private SparseArray> messagesByDaysSorted = new SparseArray<>(); public ArrayList messages = new ArrayList<>(); private SparseArray waitingForReplies = new SparseArray<>(); private LongSparseArray> polls = new LongSparseArray<>(); @@ -781,7 +805,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private float scrimPaintAlpha = 0f; private View scrimView; private float scrimViewAlpha = 1f; - private String scrimViewReaction; + private Integer scrimViewReaction; + private boolean scrimViewReactionAnimated; private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; public ActionBarPopupWindow scrimPopupWindow; @@ -813,6 +838,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int postponedScrollMinMessageId; private int postponedScrollToLastMessageQueryIndex; private int postponedScrollMessageId; + private boolean fakePostponedScroll; private boolean postponedScrollIsCanceled; private static ArrayList textSelectionHelpersCache; private ChatActivityTextSelectionHelper textSelectionHelper; @@ -955,6 +981,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, + NotificationCenter.savedMessagesDialogsUpdate, NotificationCenter.didApplyNewTheme }; @@ -1074,7 +1101,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public long getTopicId() { - return isTopic ? threadMessageId : 0L; + return isTopic || chatMode == MODE_SAVED ? threadMessageId : 0L; } public long getSavedDialogId() { @@ -1269,6 +1296,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int save_to = 25; private final static int auto_delete_timer = 26; private final static int change_colors = 27; + private final static int tag_message = 28; private final static int bot_help = 30; private final static int bot_settings = 31; @@ -1304,7 +1332,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { - if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isInSelectionMode() || inPreviewMode) { + if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isInSelectionMode() || inPreviewMode || isInsideContainer) { return false; } wasManualScroll = true; @@ -1336,7 +1364,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void startMultiselect(int position) { - if (chatMode == MODE_SAVED) { + if (isInsideContainer) { return; } int indexOfMessage = position - chatAdapter.messagesStartRow; @@ -1529,7 +1557,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!available) { return; } - selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reactionString), true, false, false); + selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reactionString), true, false, false, false); } else { TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(reactionString); if (reaction == null || cell.getMessageObject().isSponsored()) { @@ -1542,7 +1570,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!available) { return; } - selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction), true, false, false); + selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction), true, false, false, false); } } }; @@ -1697,8 +1725,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && reportType < 0) { editTextItem.setVisibility(View.VISIBLE); checkEditTextItemMenu(); - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.GONE); + if (headerItem != null) { + headerItem.setVisibility(View.GONE); + } + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(AndroidUtilities.dp(48), 0); valueAnimator.setDuration(220); @@ -1732,11 +1764,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editTextItem.setVisibility(View.GONE); if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.VISIBLE); + if (headerItem != null) { + headerItem.setVisibility(View.GONE); + } + if (attachItem != null) { + attachItem.setVisibility(View.VISIBLE); + } } else { - headerItem.setVisibility(View.VISIBLE); - attachItem.setVisibility(View.GONE); + if (headerItem != null) { + headerItem.setVisibility(View.VISIBLE); + } + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, AndroidUtilities.dp(48)); @@ -2003,7 +2043,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getMessagesController().isForum(getDialogId()) && !isTopic) { return false; } - return scheduledMessagesCount > 0 && chatMode == 0; + return scheduledMessagesCount > 0 && (chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()); } @Override @@ -2128,6 +2168,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scheduledHintShown = true; }; + public Utilities.Callback0Return insideContainerResizableView; public boolean isInsideContainer; public boolean reversed; @@ -2369,6 +2410,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addObserver(this, NotificationCenter.channelRightsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateReactions); + getNotificationCenter().addObserver(this, NotificationCenter.savedReactionTagsUpdate); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateExtendedMedia); getNotificationCenter().addObserver(this, NotificationCenter.videoLoadingStateChanged); getNotificationCenter().addObserver(this, NotificationCenter.scheduledMessagesUpdated); @@ -2467,6 +2509,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not endReached[0] = endReached[1] = true; forwardEndReached[0] = forwardEndReached[1] = true; firstLoading = false; + loading = false; checkDispatchHideSkeletons(false); } if (chatMode != MODE_PINNED && !forceHistoryEmpty) { @@ -2547,7 +2590,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (isTopic) { getMessagesController().getTopicsController().getTopicRepliesCount(dialog_id, getTopicId()); } - getMessagesController().getSavedMessagesController().preloadDialogs(); + getMessagesController().getSavedMessagesController().preloadDialogs(false); + if (chatMode == MODE_SAVED) { + getMessagesController().getSavedMessagesController().checkSavedDialogCount(getTopicId()); + } + return true; } @@ -2574,9 +2621,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } - if (chatMode == 0 && (!isThreadChat() || isTopic)) { + if ((chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()) && (!isThreadChat() || isTopic)) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, chatMode == MODE_SAVED ? 0 : threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } @@ -2739,6 +2786,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().removeObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdatePollResults); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateReactions); + getNotificationCenter().removeObserver(this, NotificationCenter.savedReactionTagsUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateExtendedMedia); getNotificationCenter().removeObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.videoLoadingStateChanged); @@ -2946,7 +2994,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not infoTopView = null; aspectRatioFrameLayout = null; videoTextureView = null; - searchAsListHint = null; mediaBanTooltip = null; noSoundHintView = null; forwardHintView = null; @@ -3002,8 +3049,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else if (id == view_as_topics) { - getMessagesController().getTopicsController().toggleViewForumAsMessages(-dialog_id, false); - TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); + if (getUserConfig().getClientUserId() == dialog_id) { + getMessagesController().setSavedViewAs(true); + avatarContainer.openProfile(false, true, true); + } else { + getMessagesController().getTopicsController().toggleViewForumAsMessages(-dialog_id, false); + TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); + } } else if (id == copy) { SpannableStringBuilder str = new SpannableStringBuilder(); long previousUid = 0; @@ -3040,6 +3092,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not createDeleteMessagesAlert(null, null); } else if (id == forward) { openForward(true); + } else if (id == tag_message) { + if (tagSelector == null) { + showTagSelector(); + } else { + hideTagSelector(); + } } else if (id == save_to) { ArrayList messageObjects = new ArrayList<>(); for (int a = 1; a >= 0; a--) { @@ -3071,39 +3129,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - if (chatMode == MODE_SAVED) { - String dialogName = ""; - long dialogId = getSavedDialogId(); - TLRPC.User user = null; - TLRPC.Chat chat = null; - if (dialogId >= 0) { - user = getMessagesController().getUser(dialogId); - } else { - chat = getMessagesController().getChat(-dialogId); - } - if (UserObject.isAnonymous(user)) { - dialogName = LocaleController.getString(R.string.AnonymousForward); - } else if (chat != null) { - dialogName = chat.title; - } else if (user != null) { - dialogName = UserObject.getUserName(user); - } - AlertDialog dialog = new AlertDialog.Builder(getContext(), getResourceProvider()) - .setTitle(LocaleController.formatString(R.string.ClearHistoryTitleSingle, dialogName)) - .setMessage(LocaleController.formatString(R.string.ClearHistoryMessageSingle, dialogName)) - .setPositiveButton(LocaleController.getString(R.string.Delete), (di, w) -> { - getMessagesController().deleteSavedDialog(getSavedDialogId()); - finishFragment(); - }) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) - .create(); - showDialog(dialog); - TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); - if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); - } - return; - } boolean canDeleteHistory = chatInfo != null && chatInfo.can_delete_channel; if (id == auto_delete_timer || id == clear_history && currentEncryptedChat == null && ((currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isDeleted(currentUser)) || (chatInfo != null && chatInfo.can_delete_channel))) { AlertsCreator.createClearDaysDialogAlert(ChatActivity.this, -1, currentUser, currentChat, canDeleteHistory, new MessagesStorage.BooleanCallback() { @@ -3202,7 +3227,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == bot_settings) { getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of("/settings", dialog_id, null, null, null, false, null, null, null, true, 0, null, false)); } else if (id == search) { - openSearchWithText(null); + openSearchWithText(isSupportedTags() ? "" : null); } else if (id == translate) { getMessagesController().getTranslateController().setHideTranslateDialog(getDialogId(), false, true); if (!getMessagesController().getTranslateController().toggleTranslatingDialog(getDialogId(), true)) { @@ -3326,6 +3351,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected boolean useAnimatedSubtitle() { return chatMode == MODE_SAVED; } + + @Override + protected boolean canSearch() { + return searchItem != null && !searching; + } + + @Override + protected void openSearch() { + openSearchWithText(isSupportedTags() ? "" : null); + } }; avatarContainer.allowShorterStatus = true; avatarContainer.premiumIconHiddable = true; @@ -3407,12 +3442,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ActionBarMenu menu = actionBar.createMenu(); if (currentEncryptedChat == null && (chatMode == 0 || chatMode == MODE_SAVED) && reportType < 0) { - searchIconItem = menu.addItem(search, R.drawable.ic_ab_search); + searchIconItem = menu.addItem(search, isSupportedTags() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search); searchIconItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem = menu.addItem(chat_menu_search, R.drawable.ic_ab_search, themeDelegate); searchItem.setIsSearchField(true); searchItem.setActionBarMenuItemSearchListener(getSearchItemListener()); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString(R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); if (chatMode == MODE_SAVED || threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() < 10) { searchItem.setVisibility(View.GONE); } else { @@ -3445,7 +3480,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); - if (chatMode == MODE_SAVED || (chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if ((chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && reportType < 0) { TLRPC.UserFull userFull = null; if (currentUser != null) { userFull = getMessagesController().getUserFull(currentUser.id); @@ -3453,7 +3488,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not headerItem = menu.addItem(chat_menu_options, R.drawable.ic_ab_other, themeDelegate); headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) { + if (currentUser != null && currentUser.self && chatMode != MODE_SAVED) { + savedChatsItem = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString(R.string.SavedViewAsChats)); + savedChatsGap = headerItem.lazilyAddColoredGap(); + savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + } else if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) { chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() { @Override public void dismiss() { @@ -3548,34 +3588,31 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (searchItem != null) { headerItem.lazilyAddSubItem(search, R.drawable.msg_search, LocaleController.getString(R.string.Search)); } - if (chatMode != MODE_SAVED) { - translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); - updateTranslateItemVisibility(); - if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { - headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); - } - if (currentUser != null) { - addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, ""); - } - if (currentEncryptedChat != null) { - timeItem2 = headerItem.lazilyAddSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString("SetTimer", R.string.SetTimer)); - } - if (currentChat != null && !isTopic) { - viewAsTopics = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString("TopicViewAsTopics", R.string.TopicViewAsTopics)); - } - if (themeDelegate.isThemeChangeAvailable(true)) { - headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("SetWallpapers", R.string.SetWallpapers)); - } - if (!isTopic) { - clearHistoryItem = headerItem.lazilyAddSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); - } + translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); + updateTranslateItemVisibility(); + if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { + headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); + } + if (currentUser != null) { + addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, ""); + } + if (currentEncryptedChat != null) { + timeItem2 = headerItem.lazilyAddSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString("SetTimer", R.string.SetTimer)); + } + if (currentChat != null && !isTopic) { + viewAsTopics = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString(R.string.TopicViewAsTopics)); + } + if (themeDelegate.isThemeChangeAvailable(true)) { + headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_background, LocaleController.getString("SetWallpapers", R.string.SetWallpapers)); + } + if (currentUser != null && currentUser.self) { + headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut)); + } + if (!isTopic) { + clearHistoryItem = headerItem.lazilyAddSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); } boolean addedSettings = false; - if (chatMode == MODE_SAVED) { - if (threadMessageId != getUserConfig().getClientUserId()) { - headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); - } - } else if (!isTopic) { + if (!isTopic) { if (ChatObject.isChannel(currentChat) && !currentChat.creator) { if (!ChatObject.isNotInChat(currentChat)) { if (currentChat.megagroup) { @@ -3596,17 +3633,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - if (chatMode != MODE_SAVED) { - if (currentUser != null && currentUser.self) { - headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); - } - if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { - if (!addedSettings) { - headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); - } - headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp)); - updateBotButtons(); + if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { + if (!addedSettings) { + headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); } + headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp)); + updateBotButtons(); } } if (ChatObject.isForum(currentChat) && isTopic && getParentLayout() != null && getParentLayout().getFragmentStack() != null && chatMode == MODE_DEFAULT) { @@ -3778,7 +3810,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onMeasure(int widthSpec, int heightSpec) { - saveScrollPosition(); +// saveScrollPosition(); super.onMeasure(widthSpec, heightSpec); } @@ -4054,7 +4086,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); boolean allowReplyOnOpenTopic = canSendMessageToTopic(message); - if (chatMode != 0 || threadMessageObjects != null && threadMessageObjects.contains(message) || + if (chatMode != 0 && (chatMode != MODE_SAVED || threadMessageId != getUserConfig().getClientUserId()) || threadMessageObjects != null && threadMessageObjects.contains(message) || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && allowReplyOnOpenTopic || message.wasJustSent) || @@ -5042,13 +5074,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ImageReceiver imageReceiver = cell.getAvatarImage(); if (imageReceiver != null) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); - if (cell.getMessageObject().deleted && !cell.getMessageObject().deletedByThanos) { - if (child.getTranslationY() != 0) { - canvas.restore(); - } - imageReceiver.setVisible(false, false); - return result; - } + boolean updateVisibility = !cell.getMessageObject().deleted && chatListView.getChildAdapterPosition(cell) != RecyclerView.NO_POSITION; boolean replaceAnimation = chatListView.isFastScrollAnimationRunning() || (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds); int top = replaceAnimation ? child.getTop() : (int) child.getY(); @@ -5233,7 +5259,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not y -= cell.getTranslationY(); } } - imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + if (updateVisibility) { + imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + } if (cell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha(cell.getAlpha()); canvas.scale( @@ -5243,7 +5271,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { imageReceiver.setAlpha(1f); } - imageReceiver.setVisible(true, false); + if (updateVisibility) { + imageReceiver.setVisible(true, false); + } imageReceiver.draw(canvas); canvas.restore(); @@ -5296,6 +5326,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } + chatListView.setHideIfEmpty(false); chatListView.setAccessibilityEnabled(false); chatListView.setNestedScrollingEnabled(false); chatListView.setInstantClick(true); @@ -5467,11 +5498,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected boolean hasSiblingChild(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int index = position - chatAdapter.messagesStartRow; - if (index >= 0 && index < messages.size()) { - MessageObject message = messages.get(index); + if (index >= 0 && index < chatAdapter.getMessages().size()) { + MessageObject message = chatAdapter.getMessages().get(index); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { - MessageObject.GroupedMessagePosition pos = group.positions.get(message); + MessageObject.GroupedMessagePosition pos = group.getPosition(message); if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -5577,11 +5608,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public int getSpanSize(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int idx = position - chatAdapter.messagesStartRow; - if (idx >= 0 && idx < messages.size()) { - MessageObject message = messages.get(idx); + if (idx >= 0 && idx < chatAdapter.getMessages().size()) { + MessageObject message = chatAdapter.getMessages().get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { - return groupedMessages.positions.get(message).spanSize; + return groupedMessages.getPosition(message).spanSize; } } } @@ -5650,6 +5681,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); scrollByTouch = false; } else { + if (searchOtherButton != null && searchOtherButton.getVisibility() == View.VISIBLE && isKeyboardVisible()) { + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + } if (newState == RecyclerView.SCROLL_STATE_SETTLING) { wasManualScroll = true; scrollingChatListView = true; @@ -5761,13 +5795,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ReactionsEffectOverlay.onScrolled(dy); checkTranslation(false); + + if (savedMessagesTagHint != null) { + if (savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } else if (!savedMessagesTagHintShown) { + lastScrollTime = System.currentTimeMillis(); + AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); + AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); + } + } } }); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - selectionReactionsOverlay = new ChatSelectionReactionMenuOverlay(this, context); - contentView.addView(selectionReactionsOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + if (getDialogId() != getUserConfig().getClientUserId()) { + selectionReactionsOverlay = new ChatSelectionReactionMenuOverlay(this, context); + contentView.addView(selectionReactionsOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } animatingImageView = new ClippingImageView(context); animatingImageView.setVisibility(View.GONE); @@ -5898,6 +5944,82 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButton.setVisibility(View.INVISIBLE); contentView.addView(pagedownButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); pagedownButton.setOnClickListener(view -> onPageDownClicked()); + ScaleStateListAnimator.apply(pagedownButton, .13f, 2f); + + searchUpButton = new FrameLayout(context); + searchUpButton.setVisibility(View.INVISIBLE); + contentView.addView(searchUpButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); + ImageView searchUpButtonImage = new ImageView(context); + searchUpButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); + Drawable drawable; + if (Build.VERSION.SDK_INT >= 21) { + searchUpButtonImage.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + } + }); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); + } else { + drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); + } + Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + drawable = combinedDrawable; + searchUpButtonImage.setBackground(drawable); + searchUpButton.addView(searchUpButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + searchUpButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchNext)); + searchUpButtonArrow = new ImageView(context); + searchUpButtonArrow.setScaleY(-1f); + searchUpButtonArrow.setImageResource(R.drawable.pagedown); + searchUpButtonArrow.setScaleType(ImageView.ScaleType.CENTER); + searchUpButtonArrow.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + searchUpButtonArrow.setPadding(0, AndroidUtilities.dp(2), 0, 0); + searchUpButton.addView(searchUpButtonArrow, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + ScaleStateListAnimator.apply(searchUpButton, .12f, 2f); + + searchDownButton = new FrameLayout(context); + searchDownButton.setVisibility(View.INVISIBLE); + contentView.addView(searchDownButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); + ImageView searchDownButtonImage = new ImageView(context); + searchDownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); + if (Build.VERSION.SDK_INT >= 21) { + searchDownButtonImage.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + } + }); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); + } else { + drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); + } + shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + drawable = combinedDrawable; + searchDownButtonImage.setBackground(drawable); + searchDownButton.addView(searchDownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + searchDownButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchPrev)); + searchDownButtonArrow = new ImageView(context); + searchDownButtonArrow.setImageResource(R.drawable.pagedown); + searchDownButtonArrow.setScaleType(ImageView.ScaleType.CENTER); + searchDownButtonArrow.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + searchDownButtonArrow.setPadding(0, AndroidUtilities.dp(2), 0, 0); + searchDownButton.addView(searchDownButtonArrow, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + ScaleStateListAnimator.apply(searchDownButton, .12f, 2f); + + searchUpButton.setOnClickListener(view -> { + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, reversed ? 2 : 1, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + showMessagesSearchListView(false); + }); + searchDownButton.setOnClickListener(view -> { + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, reversed ? 1 : 2, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + showMessagesSearchListView(false); + }); mentiondownButton = new FrameLayout(context); mentiondownButton.setVisibility(View.INVISIBLE); @@ -6282,7 +6404,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButtonImage = new ImageView(context); pagedownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); - Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { pagedownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -6294,9 +6415,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); } - Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); - CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; pagedownButtonImage.setBackground(drawable); @@ -6463,16 +6584,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messagesSearchListView.setAdapter(messagesSearchAdapter = new MessagesSearchAdapter(context, themeDelegate)); contentView.addView(messagesSearchListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); messagesSearchListView.setOnItemClickListener((view, position) -> { - getMediaDataController().jumpToSearchedMessage(classGuid, position); - showMessagesSearchListView(false); + if (searchingReaction != null) { + + if (position < 0 || position >= getMediaDataController().searchResultMessages.size()) + return; + MessageObject msg = getMediaDataController().searchResultMessages.get(position); + setFilterMessages(searchingFiltered = false, true, false); + getMediaDataController().setSearchedPosition(position); + updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); + AndroidUtilities.runOnUIThread(() -> { + scrollToMessageId(msg.getId(), 0, true, 0, true, 0, () -> { + progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, themeDelegate); + progressDialog.setOnShowListener(dialogInterface -> showPinnedProgress(false)); + progressDialog.setOnCancelListener(postponedScrollCancelListener); + progressDialog.showDelayed(500); + }); + if (waitingForLoad.isEmpty()) { + showMessagesSearchListView(false); + } + }); + } else { + getMediaDataController().jumpToSearchedMessage(classGuid, position); + showMessagesSearchListView(false); + } }); messagesSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { int lastVisibleItem = messagesSearchLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; - if (visibleItemCount > 0 && lastVisibleItem > messagesSearchLayoutManager.getItemCount() - 5) { - getMediaDataController().loadMoreSearchMessages(); + if (visibleItemCount > 0 && lastVisibleItem > messagesSearchAdapter.loadedCount - 5) { + getMediaDataController().loadMoreSearchMessages(true); } } }); @@ -7229,7 +7371,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setEmptyView(null); } else { showProgressView(false); - createEmptyView(); + createEmptyView(false); chatListView.setEmptyView(emptyViewContainer); } @@ -7240,7 +7382,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updatePinnedMessageView(false); updateInfoTopView(false); - chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); + chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager) { + @Override + public void setScrollDirection(int scrollDirection) { + if (reversed) { + if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN) { + scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + } else if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP) { + scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN; + } + } + super.setScrollDirection(scrollDirection); + } + }; chatScrollHelper.setScrollListener(this::invalidateMessagesVisiblePart); chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); @@ -7420,29 +7574,87 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not savedMessagesHint.setTextAlign(Layout.Alignment.ALIGN_CENTER); savedMessagesHint.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.SavedMessagesHint))); savedMessagesHint.setMaxWidthPx(HintView2.cutInFancyHalf(savedMessagesHint.getText(), savedMessagesHint.getTextPaint())); - savedMessagesHint.setJoint(0.5f, 0); + if (AndroidUtilities.isTablet()) { + savedMessagesHint.setJoint(0, 77); + } else { + savedMessagesHint.setJoint(0.5f, 0); + } savedMessagesHint.setCloseButton(true); - savedMessagesHint.setDuration(-1); + savedMessagesHint.setOnHiddenListener(() -> { + if (searchContainer == null || searchContainer.getVisibility() != View.VISIBLE) { + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.show(); + } + } + }); + savedMessagesHint.setDuration(-1); + savedMessagesHint.setPadding(dp(8), 0, dp(8), 0); contentView.addView(savedMessagesHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, -8, 0, 0)); + + savedMessagesSearchHint = new HintView2(context, HintView2.DIRECTION_TOP) + .setMultilineText(true) + .setTextAlign(Layout.Alignment.ALIGN_CENTER) + .setDuration(-1) + .setHideByTouch(true) + .useScale(true) + .setCloseButton(true) + .setJointPx(1, -dp(56)) + .setRounding(8); + savedMessagesSearchHint.setText(LocaleController.getString(R.string.SavedTagSearchTooltipHint)); + contentView.addView(savedMessagesSearchHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, -8, 16, 0)); + + if (getUserConfig().isPremium()) { + savedMessagesTagHint = new HintView2(context, HintView2.DIRECTION_BOTTOM) + .setMultilineText(true) + .setTextAlign(Layout.Alignment.ALIGN_CENTER) + .setDuration(-1) + .setHideByTouch(true) + .useScale(true) + .setCloseButton(true) + .setRounding(8); + savedMessagesTagHint.setText(LocaleController.getString(R.string.SavedTagLongpressHint)); + contentView.addView(savedMessagesTagHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); + } } if (getDialogId() == getUserConfig().getClientUserId()) { - actionBarSearchTags = new SearchTagsList(context, contentView, currentAccount, themeDelegate) { + actionBarSearchTags = new SearchTagsList(context, ChatActivity.this, contentView, currentAccount, getSavedDialogId(), themeDelegate, true) { @Override - protected void setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { - actionBar.clearSearchFilters(); -// if (reaction != null) { -// actionBar.setSearchFilter(new FiltersView.MediaFilterData(reaction)); + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { +// if (!isInsideContainer) { +// actionBar.clearSearchFilters(); // } searchingReaction = reaction; -// showSearchShowOther(searchingReaction != null); - getMediaDataController().searchMessagesInChat(searchItem.getSearchField().getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + searchingFiltered = reaction != null; + if (reaction == null) { + getMediaDataController().clearFoundMessageObjects(); + setFilterMessages(false); + updateSearchButtons(0, 0, -1); + } + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); + searchingQuery = searchItem.getSearchField().getText().toString(); + getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(searchingQuery) || searchingReaction != null, searchingReaction); + AndroidUtilities.hideKeyboard(searchItem.getSearchField()); + return true; } @Override - public void updateTags() { - super.updateTags(); -// showActionBarSearchTags(searchItem != null && searchItem.isSearchFieldVisible() && hasFilters()); + public void updateTags(boolean notify) { + super.updateTags(notify); + show(searchItem != null && searchItem.isSearchFieldVisible() && hasFilters()); + } + + @Override + protected void onShownUpdate(boolean finish) { + setBackgroundColor(actionBar.getBackgroundColor()); + if (tagSelector != null) { + tagSelector.setTranslationY(contentPanTranslation + getCurrentHeight()); + } + if (finish) { + invalidateChatListViewTopPadding = true; + updateChatListViewTopPadding(); + } } }; actionBarSearchTags.setVisibility(View.GONE); @@ -7453,47 +7665,422 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return fragmentView; } - private void setFilterMessages(boolean filter) { - if (chatAdapter.isFiltered == filter) return; - chatAdapter.isFiltered = filter; - if (filter) { - updateFilteredMessages(); - } else { - chatAdapter.updateRowsSafe(); - chatAdapter.notifyDataSetChanged(true); + public void setTagFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(reaction, true); + } + searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + public void setSearchQuery(String text) { + if (searchItem != null) { + searchItem.setSearchFieldText(searchingQuery = text, false); } } - private void updateFilteredMessages() { - ArrayList results = new ArrayList<>(MediaDataController.getInstance(currentAccount).getFoundMessageObjects()); - chatAdapter.filteredMessages.clear(); - for (int i = 0; i < results.size(); ++i) { - MessageObject msg = results.get(i); - MessageObject from = null; - for (int j = 0; j < messages.size(); ++j) { - MessageObject m = messages.get(j); - if (m.getDialogId() == msg.getDialogId() && m.getId() == msg.getId()) { - from = m; + public void hitSearch() { + searchWas = true; + updateSearchButtons(0, 0, -1); + getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + public void clearSearch() { + if (searchItemListener != null) { + searchItemListener.onSearchCollapse(); + } + searching = false; + searchItemVisible = false; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + protected void onSearchLoadingUpdate(boolean loading) { + + } + + private void setFilterMessages(boolean filter) { + setFilterMessages(filter, false, true); + } + private void setFilterMessages(boolean filter, boolean ignoreMessageNotFound, boolean animated) { + if (chatAdapter.isFiltered == filter) return; + chatAdapter.isFiltered = filter; + createEmptyView(true); + if (filter) { + updateFilteredMessages(false); + } + if (!saveScrollOnFilterToggle(animated, ignoreMessageNotFound)) { + chatAdapter.isFiltered = !filter; + } + if (searchOtherButton != null) { + searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagShowOtherMessages : R.string.SavedTagHideOtherMessages)); + } + updateSearchUpDownButtonVisibility(true); + showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); + if (chatListView != null) { + createEmptyView(false); + if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { + emptyViewContainer.setVisibility(View.GONE); + chatListView.setEmptyView(null); + } else { + chatListView.setEmptyView(emptyViewContainer); + chatListView.checkIfEmpty(); + } + } + } + + private boolean saveScrollOnFilterToggle(boolean animated, boolean ignoreMessageNotFound) { + final ArrayList newMessagesArray = chatAdapter.getMessages(); + + int index = -1; + int centerId = 0; + int centerStableId = 0; + int offset = 0; + int cy = chatListView.getMeasuredHeight() / 2; + ArrayList views = new ArrayList<>(); + HashMap distances = new HashMap<>(); + for (int i = 0; i < chatListView.getChildCount(); ++i) { + View child = chatListView.getChildAt(i); +// int ccy = (child.getTop() + child.getBottom()) / 2; +// views.put(Math.abs(ccy - cy), child); // base on center + int dist = (int) (chatListView.getMeasuredHeight() * .97f) - dp(42) - child.getBottom(); + if (dist < 0) continue; + distances.put(child, dist); + views.add(child); + } + Collections.sort(views, Comparator.comparingInt(distances::get)); + HashSet ids = new HashSet(); + HashSet stableIds = new HashSet(); + for (int i = 0; i < newMessagesArray.size(); ++i) { + MessageObject m = newMessagesArray.get(i); + if (!m.isDateObject) { + ids.add(m.getId()); + } + stableIds.add(m.stableId); + } + for (int i = 0; i < views.size(); ++i) { + View child = views.get(i); + MessageObject msg; + if (child instanceof ChatMessageCell) { + msg = ((ChatMessageCell) child).getMessageObject(); + } else if (child instanceof ChatActionCell) { + msg = ((ChatActionCell) child).getMessageObject(); + } else { + continue; + } + if (msg == null) continue; + int id = msg.getId(); + if (ids.contains(id)) { + centerId = id; + offset = getScrollingOffsetForView(child); + break; + } else if (stableIds.contains(msg.stableId)) { + centerStableId = msg.stableId; + offset = getScrollingOffsetForView(child); + break; + } + } + if (centerId == 0 && centerStableId == 0) { + if (!chatAdapter.isFiltered && !ignoreMessageNotFound) { + for (int j = 0; j < views.size(); ++j) { + View centerView = views.get(j); + MessageObject msg; + if (centerView instanceof ChatMessageCell) { + msg = ((ChatMessageCell) centerView).getMessageObject(); + } else { + continue; + } + if (msg == null) { + continue; + } + int id = msg.getId(); + + waitingForLoad.clear(); + removeSelectedMessageHighlight(); + scrollToMessagePosition = -10000; + startLoadFromMessageId = id; + showScrollToMessageError = false; + createUnreadMessageAfterIdLoading = false; + postponedScrollIsCanceled = false; + waitingForLoad.add(lastLoadIndex); + postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = true; + postponedScrollMinMessageId = minMessageId[0]; + postponedScrollMessageId = id; + getMessagesController().loadMessages(dialog_id, 0, false, 50, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + return false; + } + } + for (int j = 0; j < views.size(); ++j) { + View centerView = views.get(j); + MessageObject msg; + if (centerView instanceof ChatMessageCell) { + msg = ((ChatMessageCell) centerView).getMessageObject(); + } else { + continue; + } + if (msg == null) { + continue; + } + int id = msg.getId(); + int mid = -1; + int leastDist = Integer.MAX_VALUE; + for (int i = 0; i < newMessagesArray.size(); ++i) { + MessageObject msg2 = newMessagesArray.get(i); + if (msg2.getId() == 0) continue; + final int dist = Math.abs(msg2.getId() - id); + if (dist < leastDist) { + leastDist = dist; + mid = msg2.getId(); + + index = i; + offset = 0; + } + } + if (mid != -1) { break; } } - if (msg.stableId == 0) { - msg.checkMediaExistance(); - if (from != null) { - msg.copyStableParams(from); - } else { - msg.stableId = lastStableId++; + } + if (centerStableId != 0) { + for (int i = 0; i < newMessagesArray.size(); ++i) { + if (newMessagesArray.get(i).stableId == centerStableId) { + index = i; + break; } } + } else if (centerId != 0) { + for (int i = 0; i < newMessagesArray.size(); ++i) { + if (newMessagesArray.get(i).getId() == centerId) { + index = i; + break; + } + } + } + chatAdapter.updateRowsSafe(); + if (index >= 0) { + int newPosition = chatAdapter.messagesStartRow + index; + chatLayoutManager.scrollToPositionWithOffset(newPosition, offset); + } + chatAdapter.notifyDataSetChanged(animated); + return true; + } + + private LongSparseArray> filteredMessagesByDays; + private LongSparseArray filteredMessagesDict; + + private void putFilteredDate(int index, MessageObject baseMsg) { + TLRPC.Message dateMsg = new TLRPC.TL_message(); + dateMsg.message = LocaleController.formatDateChat(baseMsg.messageOwner.date); + dateMsg.id = 0; + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(((long) baseMsg.messageOwner.date) * 1000); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); + MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); + dateObj.type = 10; + dateObj.contentType = 1; + dateObj.isDateObject = true; + dateObj.stableId = getStableIdForDateObject(baseMsg.dateKeyInt); + chatAdapter.filteredMessages.add(index, dateObj); + } + + private void createHint2MessageObject() { + if (hint2MessageObject != null) return; + TLRPC.Message dateMsg = new TLRPC.TL_message(); + dateMsg.message = LocaleController.getString(R.string.SavedMessagesProfileHint); + dateMsg.id = 0; + hint2MessageObject = new MessageObject(currentAccount, dateMsg, false, false); + hint2MessageObject.type = 10; + hint2MessageObject.contentType = 1; + } + + private void updateFilteredMessages(boolean notify) { + ArrayList results = new ArrayList<>(MediaDataController.getInstance(currentAccount).getFoundMessageObjects()); + if (filteredMessagesDict == null) { + filteredMessagesDict = new LongSparseArray<>(); + } + if (filteredMessagesByDays == null) { + filteredMessagesByDays = new LongSparseArray<>(); + } else { + filteredMessagesByDays.clear(); + } + LongSparseArray newGroups = null; + LongSparseArray changedGroups = null; + chatAdapter.filteredMessages.clear(); + filteredMessagesDict.clear(); + for (int i = 0; i < results.size(); ++i) { + MessageObject msg = results.get(i); + MessageObject from = null; + if (from == null) { + for (int j = 0; j < messages.size(); ++j) { + MessageObject m = messages.get(j); + if (m.getDialogId() == msg.getDialogId() && m.getId() == msg.getId()) { + from = m; + break; + } + } + } + if (msg.stableId == 0) { + if (from == null) { + msg.checkMediaExistance(); + } else { + msg.mediaExists = from.mediaExists; + msg.attachPathExists = from.attachPathExists; + } + } + if (from != null) { + msg.isSaved = from.isSaved; + if (chatAdapter.isFiltered && msg.stableId != 0) { + from.copyStableParams(msg); + } else { + msg.copyStableParams(from); + } + } else if (msg.stableId == 0) { + msg.stableId = lastStableId++; + } + msg.isOutOwnerCached = null; + if (msg.messageOwner != null) { + msg.messageOwner.out = true; + } + msg.isOutOwner(); + + if (msg.hasValidGroupId()) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(msg.getGroupIdForUse()); + if (groupedMessages == null) { + groupedMessages = new MessageObject.GroupedMessages(); + groupedMessages.reversed = reversed; + groupedMessages.groupId = msg.getGroupId(); + groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); + } else if (newGroups == null || newGroups.indexOfKey(msg.getGroupId()) < 0) { + if (changedGroups == null) { + changedGroups = new LongSparseArray<>(); + } + changedGroups.put(msg.getGroupId(), groupedMessages); + } + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + if (groupedMessages.getPosition(msg) == null) { + boolean found = false; + for (int j = 0; j < groupedMessages.messages.size(); ++j) { + if (groupedMessages.messages.get(j).getId() == msg.getId()) { + found = true; + break; + } + } + if (!found) { + groupedMessages.messages.add(msg); + } + } + } else if (msg.getGroupIdForUse() != 0) { + msg.messageOwner.grouped_id = 0; + msg.localSentGroupId = 0; + } + + chatAdapter.filteredMessages.add(msg); + filteredMessagesDict.put(msg.getId(), msg); + } + if (newGroups != null) { + for (int i = 0; i < newGroups.size(); ++i) { + MessageObject.GroupedMessages group = newGroups.valueAt(i); + Collections.sort(group.messages, (a, b) -> a.getId() - b.getId()); + group.calculate(); + } + } + ArrayList messagesResults = new ArrayList<>(); + if (searchingReaction != null && TextUtils.isEmpty(searchingQuery)) { + for (int i = 0; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg != null && msg.messageOwner != null && msg.messageOwner.reactions != null && msg.messageOwner.reactions.reactions_as_tags) { + for (int j = 0; j < msg.messageOwner.reactions.results.size(); ++j) { + if (searchingReaction.isSame(msg.messageOwner.reactions.results.get(j).reaction)) { + messagesResults.add(msg); + break; + } + } + } + } + } + for (int i = 0; i < messagesResults.size(); ++i) { + MessageObject msg = messagesResults.get(i); + if (filteredMessagesDict.containsKey(msg.getId())) { + continue; + } msg.isOutOwnerCached = null; if (msg.messageOwner != null) { msg.messageOwner.out = true; } chatAdapter.filteredMessages.add(msg); + filteredMessagesDict.put(msg.getId(), msg); + } + for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { + MessageObject obj = chatAdapter.filteredMessages.get(i); + if (!obj.hasValidGroupId()) { + continue; + } + MessageObject.GroupedMessages group = groupedMessagesMap.get(obj.getGroupId()); + if (group != null) { + for (int j = group.messages.size() - 1; j >= 0; --j) { + MessageObject groupmsg = group.messages.get(j); + if (groupmsg == obj || filteredMessagesDict.containsKey(groupmsg.getId())) + continue; + chatAdapter.filteredMessages.add(i, groupmsg); + filteredMessagesDict.put(groupmsg.getId(), groupmsg); + i++; + } + } else { + + } + } + Collections.sort(chatAdapter.filteredMessages, (a, b) -> b.getId() - a.getId()); + MessageObject lastFilteredMessage = null; + for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { + MessageObject msg = chatAdapter.filteredMessages.get(i); + if (reversed && msg != null && i == 0) { + putFilteredDate(i++, msg); + } + if (!reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { + putFilteredDate(i++, lastFilteredMessage); + } + ArrayList dayArray = filteredMessagesByDays.get(msg.dateKeyInt); + if (dayArray == null) { + filteredMessagesByDays.put(msg.dateKeyInt, dayArray = new ArrayList<>()); + } + dayArray.add(msg); + if (reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { + putFilteredDate(i++, msg); + } + lastFilteredMessage = msg; + if (!reversed && lastFilteredMessage != null && i >= chatAdapter.filteredMessages.size() - 1) { + putFilteredDate(chatAdapter.filteredMessages.size(), lastFilteredMessage); + i++; + } } chatAdapter.filteredEndReached = MediaDataController.getInstance(currentAccount).searchEndReached(); - chatAdapter.updateRowsSafe(); - chatAdapter.notifyDataSetChanged(true); + if (notify) { + chatAdapter.updateRowsSafe(); + chatAdapter.notifyDataSetChanged(true); + showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); + if (chatListView != null) { + createEmptyView(false); + if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { + emptyViewContainer.setVisibility(View.GONE); + chatListView.setEmptyView(null); + } else { + chatListView.setEmptyView(emptyViewContainer); + chatListView.checkIfEmpty(); + } + } + } } private void createBottomMessagesActionButtons() { @@ -7870,22 +8457,190 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); if (currentEncryptedChat == null) { - actionModeViews.add(actionMode.addItemWithWidth(save_to, R.drawable.msg_download, AndroidUtilities.dp(54), LocaleController.getString("SaveToMusic", R.string.SaveToMusic))); - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); + actionModeViews.add(actionMode.addItemWithWidth(save_to, R.drawable.msg_download, AndroidUtilities.dp(54), LocaleController.getString(R.string.SaveToMusic))); + actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.Edit))); + if (getDialogId() == getUserConfig().getClientUserId() && (chatMode == 0 || chatMode == MODE_SAVED)) { + actionModeViews.add(actionMode.addItemWithWidth(tag_message, R.drawable.menu_tag_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.AccDescrTagMessage))); + } + actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString(R.string.AddToFavorites))); + actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString(R.string.Copy))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString(R.string.Forward))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString(R.string.Delete))); } else { - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); + actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.Edit))); + actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString(R.string.AddToFavorites))); + actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString(R.string.Copy))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString(R.string.Delete))); } - actionMode.getItem(edit).setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); - actionMode.getItem(copy).setVisibility(!getMessagesController().isChatNoForwards(currentChat) && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); - actionMode.getItem(star).setVisibility(selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0 ? View.VISIBLE : View.GONE); - actionMode.getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(edit, canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(copy, !getMessagesController().isChatNoForwards(currentChat) && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(star, selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(delete, cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(tag_message, getUserConfig().isPremium() ? View.VISIBLE : View.GONE); + } + + private void hideTagSelector() { + if (tagSelector == null) return; + final ReactionsContainerLayout thisTagSelector = tagSelector; + tagSelector = null; + thisTagSelector.dismissWindow(); + if (thisTagSelector.getReactionsWindow() != null && thisTagSelector.getReactionsWindow().containerView != null) { + thisTagSelector.getReactionsWindow().containerView.animate().alpha(0).setDuration(180).start(); + } + thisTagSelector.animate().alpha(0.01f).translationY(-dp(12)).scaleX(.7f).scaleY(.7f).withEndAction(() -> { + contentView.removeView(thisTagSelector); + }).setDuration(180).start(); + } + + private ReactionsContainerLayout tagSelector; + private void showTagSelector() { + if (getDialogId() != getUserConfig().getClientUserId() || !getUserConfig().isPremium()) return; + if (tagSelector != null) return; + tagSelector = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_TAGS, this, getContext(), currentAccount, themeDelegate) { + + private int[] loc = new int[2]; + + private ValueAnimator va; + private boolean firstLayout = true; + private void updateBubbleOffset(float x, boolean animated) { + if (va != null) { + va.cancel(); + va = null; + } + if (!animated) { + setBubbleOffset(x); + } else { + va = ValueAnimator.ofFloat(bubblesOffset, x); + va.addUpdateListener(anm -> { + setBubbleOffset((float) anm.getAnimatedValue()); + invalidate(); + }); + va.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + va.setDuration(420); + va.start(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + final ActionBarMenu actionMode = actionBar.createActionMode(); + View item = actionMode.getItem(tag_message); + if (item != null) { + getLocationInWindow(loc); + float x = getX(); + float x2 = x + getWidth(); + item.getLocationInWindow(loc); + float cx = loc[0] + item.getWidth() / 2f + dp(20) * (LocaleController.isRTL ? -1 : 1); + + if (LocaleController.isRTL) { + updateBubbleOffset(cx - x, !firstLayout); + } else { + updateBubbleOffset(cx - x2, !firstLayout); + } + firstLayout = false; + } + } + }; + tagSelector.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(24), AndroidUtilities.dp(4), AndroidUtilities.dp(0)); + tagSelector.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { + @Override + public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { + if (tagSelector == null) return; + if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium()) { + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + clearSelectionMode(false); + return; + } + boolean updateFilteredMessages = false; + boolean notifyFilteredMessages = false; + boolean remove = tagSelector.getSelectedReactions().contains(visibleReaction); + HashSet groupsChecked = new HashSet<>(); + int messagesCount = 0; + for (int a = 0; a < selectedMessagesIds.length; ++a) { + for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { + MessageObject messageObject = selectedMessagesIds[a].valueAt(k); + if (messageObject.hasValidGroupId()) { + MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); + if (group == null || groupsChecked.contains(group.groupId)) + continue; + groupsChecked.add(group.groupId); + messageObject = group.findPrimaryMessageObject(); + if (messageObject == null) continue; + } + if (messageObject.hasReaction(visibleReaction) == remove) { + selectReaction(messageObject, null, null, 0, 0, visibleReaction, false, false, false, true); + if (!remove) { + messagesCount++; + } + } + if (messageObject != null && messageObject.messageOwner != null) { + if (chatAdapter.isFiltered) { + MessageObject realMessage = messagesDict[0].get(messageObject.getId()); + if (realMessage != null && realMessage.messageOwner != null) { + realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; + } + } else if (!chatAdapter.isFiltered && searchingReaction != null) { + updateFilteredMessages = true; + } + } + if (chatAdapter.isFiltered && !messageObject.hasReaction(searchingReaction)) { + final MessageObject msg = messageObject; + final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); + if (groupedMessages != null) { + for (int i = 0; i < groupedMessages.messages.size(); ++i) { + MessageObject gmsg = groupedMessages.messages.get(i); + getMediaDataController().removeMessageFromResults(gmsg.getId()); + } + } else { + getMediaDataController().removeMessageFromResults(msg.getId()); + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } + updateFilteredMessages = true; + notifyFilteredMessages = true; + } + } + } + if (updateFilteredMessages) { + updateFilteredMessages(notifyFilteredMessages); + } + clearSelectionMode(true); + + if (messagesCount > 0) { + TLRPC.Document document; + if (visibleReaction.documentId == 0) { + TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(visibleReaction.emojicon); + if (availableReaction == null) { + return; + } + document = availableReaction.activate_animation; + } else { + document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, visibleReaction.documentId); + } + + if (document == null) { + return; + } + + BulletinFactory.of(ChatActivity.this).createMessagesTaggedBulletin(messagesCount, document, null).show(true); + } + } + }); + tagSelector.setTop(true); + tagSelector.setClipChildren(false); + tagSelector.setClipToPadding(false); + tagSelector.setVisibility(View.VISIBLE); + tagSelector.setHint(LocaleController.getString(tagSelector.getSelectedReactions().isEmpty() ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); + contentView.addView(tagSelector, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); + tagSelector.setMessage(null, null); + tagSelector.setTranslationY(-dp(12)); + tagSelector.setScaleY(.4f); + tagSelector.setScaleX(.4f); + tagSelector.animate().scaleY(1f).scaleX(1f).translationY(0).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + updateSelectedMessageReactions(); + tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); } private void createSearchContainer() { @@ -7919,7 +8674,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (chatListView != null && isInsideContainer) { + chatListView.setPadding(chatListView.getPaddingLeft(), chatListView.getPaddingTop(), chatListView.getPaddingRight(), AndroidUtilities.dp(3) + blurredViewBottomOffset + (isInsideContainer && visibility == VISIBLE ? dp(50) : 0)); + } + } }; + searchContainer.setClickable(false); searchContainer.drawBlur = false; searchContainer.isTopView = false; searchContainer.setWillNotDraw(false); @@ -7927,53 +8691,46 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchContainer.setPadding(0, AndroidUtilities.dp(3), 0, 0); searchContainer.setClipToPadding(false); - searchAsListTogglerView = new View(getContext()); - searchAsListTogglerView.setOnTouchListener((v, event) -> getMediaDataController().getFoundMessageObjects().size() <= 1); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - searchAsListTogglerView.setBackground(Theme.getSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false)); - } - searchAsListTogglerView.setOnClickListener(v -> { - if (getMediaDataController().getFoundMessageObjects().size() > 1) { - if (searchAsListHint != null) { - searchAsListHint.hide(); - } - toggleMesagesSearchListView(); - if (!SharedConfig.searchMessagesAsListUsed) { - SharedConfig.setSearchMessagesAsListUsed(true); - } - } - }); - final float paddingTop = Theme.chat_composeShadowDrawable.getIntrinsicHeight() / AndroidUtilities.density - 3f; - searchContainer.addView(searchAsListTogglerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, paddingTop, 0, 0)); + searchCountText = new AnimatedTextView(getContext(), true, true, true); + searchCountText.setAnimationProperties(.25f, 0, 280, CubicBezierInterpolator.EASE_OUT_QUINT); +// searchCountText.setScaleProperty(.5f); + searchCountText.setTextSize(dp(15)); + searchCountText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchCountText.setTextColor(getThemedColor(Theme.key_chat_searchPanelText)); + searchCountText.setGravity(Gravity.LEFT); + searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.CENTER_VERTICAL, 0, -1, 97.33f, 0)); + contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, searchContainerHeight, Gravity.BOTTOM)); - searchUpButton = new ImageView(getContext()); - searchUpButton.setScaleType(ImageView.ScaleType.CENTER); - searchUpButton.setImageResource(R.drawable.msg_go_up); - searchUpButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); - searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); - searchUpButton.setOnClickListener(view -> { - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); - showMessagesSearchListView(false); - if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) { - showSearchAsListHint(); - searchAsListHintShown = true; - SharedConfig.increaseSearchAsListHintShows(); - } + searchExpandList = new AnimatedTextView(getContext(), true, false, true); + searchExpandList.setAnimationProperties(0, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + searchExpandList.setScaleProperty(.7f); + searchExpandList.setTextSize(dp(15)); + searchExpandList.setGravity(Gravity.RIGHT); + searchExpandList.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchExpandList.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlueText2)); + searchExpandList.setText(LocaleController.getString(messagesSearchListView != null && messagesSearchListView.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList)); + searchExpandList.adaptWidth = false; + searchExpandList.setPadding(dp(15.33f), 0, dp(15.33f), 0); + searchExpandList.setOnClickListener(v -> { + toggleMesagesSearchListView(); }); - searchUpButton.setContentDescription(LocaleController.getString("AccDescrSearchNext", R.string.AccDescrSearchNext)); + searchExpandList.setAlpha(0.5f); + searchExpandList.setClickable(false); + searchContainer.addView(searchExpandList, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.FILL_VERTICAL)); - searchDownButton = new ImageView(getContext()); - searchDownButton.setScaleType(ImageView.ScaleType.CENTER); - searchDownButton.setImageResource(R.drawable.msg_go_down); - searchDownButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); - searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); - searchDownButton.setOnClickListener(view -> { - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); - showMessagesSearchListView(false); + searchOtherButton = new AnimatedTextView(getContext(), true, true, true); + searchOtherButton.setGravity(Gravity.CENTER); + searchOtherButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchOtherButton.setTextColor(getThemedColor(Theme.key_chat_fieldOverlayText)); + searchOtherButton.setTextSize(AndroidUtilities.dp(15)); + searchOtherButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_windowBackgroundWhite), Theme.blendOver(getThemedColor(Theme.key_windowBackgroundWhite), getThemedColor(Theme.key_listSelector)))); + searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagHideOtherMessages : R.string.SavedTagShowOtherMessages)); + searchOtherButton.setOnClickListener(v -> { + setFilterMessages(!chatAdapter.isFiltered); }); - searchDownButton.setContentDescription(LocaleController.getString("AccDescrSearchPrev", R.string.AccDescrSearchPrev)); + searchOtherButton.setVisibility(View.GONE); + searchOtherButton.setAlpha(0f); + searchContainer.addView(searchOtherButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); if (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { searchUserButton = new ImageView(getContext()); @@ -8005,7 +8762,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchCalendarButton.setImageResource(R.drawable.msg_calendar); searchCalendarButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchCalendarButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 2.66f, 0, 0, 0)); searchCalendarButton.setOnClickListener(view -> { if (getParentActivity() == null) { return; @@ -8019,28 +8776,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, themeDelegate).create()); }); searchCalendarButton.setContentDescription(LocaleController.getString("JumpToDate", R.string.JumpToDate)); - - searchCountText = new SearchCounterView(getContext(), themeDelegate); - searchCountText.setGravity(Gravity.LEFT); - searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 108, 0)); - contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, searchContainerHeight, Gravity.BOTTOM)); - - searchOtherButton = new AnimatedTextView(getContext(), true, true, true); - searchOtherButton.setGravity(Gravity.CENTER); - searchOtherButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - searchOtherButton.setTextColor(getThemedColor(Theme.key_chat_fieldOverlayText)); - searchOtherButton.setTextSize(AndroidUtilities.dp(15)); - searchOtherButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_windowBackgroundWhite), Theme.blendOver(getThemedColor(Theme.key_windowBackgroundWhite), getThemedColor(Theme.key_listSelector)))); - searchOtherButton.setVisibility(View.GONE); - searchOtherButton.setAlpha(0f); - searchContainer.addView(searchOtherButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); } private void showSearchShowOther(boolean show) { searchOtherButton.setVisibility(View.VISIBLE); searchOtherButton.animate().alpha(show ? 1f : 0f).withEndAction(() -> { searchOtherButton.setVisibility(show ? View.VISIBLE : View.GONE); - }).start(); + }).setDuration(170).start(); } public void onPageDownClicked() { @@ -8212,7 +8954,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean filledEditTextItemMenu = false; private void checkEditTextItemMenu() { - if (filledEditTextItemMenu) { + if (filledEditTextItemMenu || editTextItem == null) { return; } @@ -8250,13 +8992,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void updatePagedownButtonsPosition() { float baseTranslationY = chatActivityEnterView.getAnimatedTop() + chatActivityEnterView.getTranslationY() + (chatActivityEnterTopView.getVisibility() == View.VISIBLE ? chatActivityEnterTopView.getTranslationY() : 0); if (pagedownButton != null) { - pagedownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - pagedownButtonEnterProgress)); + pagedownButton.setTranslationY(baseTranslationY + dp(100) * (1f - pagedownButtonEnterProgress)); + } + if (searchUpButton != null) { + searchUpButton.setTranslationY(baseTranslationY - dp(51.33f) * searchUpDownEnterProgress + dp(100) * (1f - searchUpDownEnterProgress)); + } + if (searchDownButton != null) { + searchDownButton.setTranslationY(baseTranslationY + dp(100) * (1f - searchUpDownEnterProgress)); } if (mentiondownButton != null) { - mentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - mentionsButtonEnterProgress) - (AndroidUtilities.dp(72) * pagedownButtonEnterProgress) * mentionsButtonEnterProgress); + mentiondownButton.setTranslationY(baseTranslationY + dp(100) * (1f - mentionsButtonEnterProgress) - (dp(72) * pagedownButtonEnterProgress) * mentionsButtonEnterProgress); } if (reactionsMentiondownButton != null) { - reactionsMentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - reactionsMentionButtonEnterProgress) - ((AndroidUtilities.dp(50) + AndroidUtilities.dp(22) * pagedownButtonCounter.getEnterProgress()) * pagedownButtonEnterProgress + AndroidUtilities.dp(72) * mentionsButtonEnterProgress) * reactionsMentionButtonEnterProgress); + reactionsMentiondownButton.setTranslationY(baseTranslationY + dp(100) * (1f - reactionsMentionButtonEnterProgress) - ((dp(50) + dp(22) * pagedownButtonCounter.getEnterProgress()) * pagedownButtonEnterProgress + dp(72) * mentionsButtonEnterProgress) * reactionsMentionButtonEnterProgress); } if (suggestEmojiPanel != null) { suggestEmojiPanel.setTranslationY(baseTranslationY); @@ -8609,7 +9357,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchItem.setSearchFieldHint(null); searchItem.clearSearchText(); - getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + getMediaDataController().searchMessagesInChat(searchingQuery = "", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } private void updateTranslateItemVisibility() { @@ -9218,6 +9966,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return liteModeChat; } + private void showProgressView(boolean show) { if (progressView == null) { return; @@ -9309,6 +10058,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (isThreadChat() && (!isTopic || pinnedOnlyStarterMessage())) { pinnedViewH = 0; } + if (actionBarSearchTags != null) { + pinnedViewH = Math.max(pinnedViewH, actionBarSearchTags.getCurrentHeight()); + } float pendingViewH = 0; View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) { @@ -9320,9 +10072,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; float searchExpandOffset = 0; - if (actionBarSearchTags != null && actionBarSearchTags.shown()) { - chatListViewPaddingTop += actionBarSearchTags.getMeasuredHeight(); - } if (searchExpandProgress != 0 && chatActivityEnterView.getVisibility() == View.VISIBLE) { chatListViewPaddingTop -= (searchExpandOffset = searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(searchContainerHeight))); } @@ -9350,7 +10099,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not floatingDateView.setTranslationY(chatListView.getTranslationY() - searchExpandOffset + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); } - int p = isInsideContainer ? 0 : chatListView.getMeasuredHeight() * 2 / 3; + int p = isInsideContainer ? dp(4) : chatListView.getMeasuredHeight() * 2 / 3; if (chatListView != null && chatLayoutManager != null && chatAdapter != null) { if (chatListView.getPaddingTop() != p) { @@ -9369,7 +10118,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset); + chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset + (isInsideContainer && searchContainer != null && searchContainer.getVisibility() == View.VISIBLE ? dp(50) : 0)); if (scrollToMessageObject != null) { chatAdapter.updateRowsSafe(); @@ -9431,25 +10180,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not translation += pendingRequestsDelegate.getViewEnterOffset(); pendingRequestsView.setTranslationY(translation); } + float p = actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0; if (fragmentContextView != null) { float from = 0; if (fragmentLocationContextView != null && fragmentLocationContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(36); } - fragmentContextView.setTranslationY(contentPanTranslation + from + fragmentContextView.getTopPadding()); + fragmentContextView.setTranslationY(contentPanTranslation + p + from + fragmentContextView.getTopPadding()); } if (fragmentLocationContextView != null) { float from = 0; if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(fragmentContextView.getStyleHeight()) + fragmentContextView.getTopPadding(); } - fragmentLocationContextView.setTranslationY(contentPanTranslation + from + fragmentLocationContextView.getTopPadding()); + fragmentLocationContextView.setTranslationY(contentPanTranslation + p + from + fragmentLocationContextView.getTopPadding()); } if (topChatPanelView != null) { - topChatPanelView.setTranslationY(contentPanTranslation + contentPaddingTop + topChatPanelViewOffset); + topChatPanelView.setTranslationY(contentPanTranslation + p + contentPaddingTop + topChatPanelViewOffset); } if (alertView != null && alertView.getVisibility() == View.VISIBLE) { - alertView.setTranslationY(contentPanTranslation + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); + alertView.setTranslationY(contentPanTranslation + p + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); } if (bottomOverlayChat != null) { bottomOverlayChat.setTranslationY(bottomPanelTranslationYReverse); @@ -9838,7 +10588,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject.GroupedMessages groupedMessages = null; if (message.getGroupId() != 0) { groupedMessages = groupedMessagesMap.get(message.getGroupId()); - if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { + if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.getPosition(message) == null)) { groupedMessages = null; } } @@ -9886,6 +10636,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not progressDialog.showDelayed(1000); postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; waitingForLoad.add(lastLoadIndex); postponedScrollMessageId = 0; postponedScrollIsCanceled = false; @@ -10083,7 +10834,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openKeyboardOnAttachMenuClose = false; } } - if (resetAdjust) { + if (resetAdjust && !isInsideContainer) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } @@ -10199,6 +10950,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messagesSearchListView.setVisibility(View.VISIBLE); } messagesSearchListView.setTag(show ? 1 : null); + messagesSearchListView.setPadding(0, actionBarSearchTags != null ? actionBarSearchTags.getHeight() : 0, 0, 0); messagesSearchListViewAnimation = new AnimatorSet(); messagesSearchListViewAnimation.playTogether(ObjectAnimator.ofFloat(messagesSearchListView, View.ALPHA, show ? 1.0f : 0.0f)); messagesSearchListViewAnimation.setInterpolator(CubicBezierInterpolator.EASE_IN); @@ -10222,7 +10974,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); messagesSearchListViewAnimation.start(); - + if (searchExpandList != null) { + searchExpandList.setText(LocaleController.getString(messagesSearchListView != null && messagesSearchListView.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList), !LocaleController.isRTL); + } + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } public boolean playFirstUnreadVoiceMessage() { @@ -10364,9 +11121,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (slowModeHint != null) { slowModeHint.hide(); } - if (searchAsListHint != null) { - searchAsListHint.hide(); - } if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } @@ -10441,20 +11195,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not timerHintView.showForView(avatarContainer.getTimeItem(), true); } - private void showSearchAsListHint() { - if (getParentActivity() == null || fragmentView == null || searchCountText == null) { - return; - } - if (searchAsListHint == null) { - searchAsListHint = new HintView(getParentActivity(), HintView.TYPE_SEARCH_AS_LIST, themeDelegate); - searchAsListHint.setAlpha(0.0f); - searchAsListHint.setVisibility(View.INVISIBLE); - searchAsListHint.setText(LocaleController.getString("TapToViewAsList", R.string.TapToViewAsList)); - contentView.addView(searchAsListHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); - } - searchAsListHint.showForView(searchCountText, true); - } - private void showScheduledHint() { boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3 || chatActivityEnterView.isEditingMessage()) { @@ -10950,11 +11690,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatLayoutManager == null || paused || chatAdapter.isFrozen || waitingForGetDifference) { return; } - if (chatAdapter.isFiltered) { - getMediaDataController().loadMoreSearchMessages(); - return; - } int firstVisibleItem = RecyclerListView.NO_POSITION; + int lastVisibleItem = RecyclerListView.NO_POSITION; int visibleItemCount = 0; for (int i = 0; i < chatListView.getChildCount(); i++) { int position = chatListView.getChildAdapterPosition(chatListView.getChildAt(i)); @@ -10962,9 +11699,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (firstVisibleItem == RecyclerListView.NO_POSITION || position < firstVisibleItem) { firstVisibleItem = position; } + if (lastVisibleItem == RecyclerListView.NO_POSITION || position > lastVisibleItem) { + lastVisibleItem = position; + } visibleItemCount++; } } + if (chatAdapter.isFiltered) { + if (chatAdapter.loadingUpRow >= 0 && firstVisibleItem >= 0 && chatAdapter.loadingUpRow >= firstVisibleItem && chatAdapter.loadingUpRow <= lastVisibleItem) { + getMediaDataController().loadMoreSearchMessages(false); + } + return; + } final int firstVisibleItemFinal = firstVisibleItem; final int visibleItemCountFinal = visibleItemCount; int totalItemCount = chatAdapter.getItemCount(); @@ -12435,9 +13181,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return () -> getMessagesController().doDeleteShowOnceTask(taskId, dialog_id, messageObject.getId()); } - private void clearChatData() { + private void clearChatData(boolean full) { messages.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); waitingForLoad.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; @@ -12463,10 +13210,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cacheEndReached[a] = false; forwardEndReached[a] = true; } - first = true; - firstLoading = true; - loading = true; - loadingForward = false; + if (full) { + first = true; + firstLoading = true; + loading = true; + loadingForward = false; + } waitingForReplyMessageLoad = false; startLoadFromMessageId = 0; showScrollToMessageError = false; @@ -12475,7 +13224,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not createUnreadMessageAfterId = 0; createUnreadMessageAfterIdLoading = false; needSelectFromMessageId = false; - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyDataSetChanged(false); } } @@ -12553,6 +13302,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; postponedScrollMessageId = 0; postponedScrollIsCanceled = false; waitingForLoad.clear(); @@ -12984,7 +13734,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } - floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); + if (messageObject != null && messageObject.messageOwner != null) { + floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); + } } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); @@ -13387,7 +14139,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forceNextPinnedMessageId = Math.abs(forcePinnedMessageId); forceScrollToFirst = forcePinnedMessageId > 0; wasManualScroll = true; - MessageObject object = messagesDict[loadIndex].get(id); + MessageObject object = chatAdapter.isFiltered ? (filteredMessagesDict != null ? filteredMessagesDict.get(id) : null) : messagesDict[loadIndex].get(id); boolean query = false; int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; int scrollFromIndex = 0; @@ -13397,14 +14149,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollDown = !scrollDown; } scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; - } else if (messages.size() > 0) { + } else if (chatAdapter.getMessages().size() > 0) { if (isThreadChat() && id == threadMessageId) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else { int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { - MessageObject messageObject = messages.get(i - chatAdapter.messagesStartRow); + MessageObject messageObject = chatAdapter.getMessages().get(i - chatAdapter.messagesStartRow); if (messageObject.getId() == 0 || messageObject.isSponsored()) { continue; } @@ -13430,7 +14182,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - int index = messages.indexOf(object); + int index = chatAdapter.getMessages().indexOf(object); if (index != -1) { if (scrollFromIndex > 0) { scrollDirection = scrollFromIndex > index ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; @@ -13442,7 +14194,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatAdapter.updateRowsSafe(); - int position = chatAdapter.messagesStartRow + messages.indexOf(object); + int position = chatAdapter.messagesStartRow + chatAdapter.getMessages().indexOf(object); updateVisibleRows(); boolean found = false; @@ -13534,11 +14286,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not postponedScrollIsCanceled = false; waitingForLoad.add(lastLoadIndex); postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; - AndroidUtilities.runOnUIThread(() -> { - getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, ((isThreadChat() && !isTopic) || AndroidUtilities.isTablet()) ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - }, SCROLL_DEBUG_DELAY ? 7500 : 0); + getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, ((isThreadChat() && !isTopic) || AndroidUtilities.isTablet()) ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } else { View child = chatListView.getChildAt(0); if (child != null && child.getTop() <= 0) { @@ -13573,7 +14324,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pagedownButton == null) { return; } - boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo() && !isInsideContainer; + boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo() && !isInsideContainer && (!searching || getMediaDataController().searchResultMessages.isEmpty()); if (show) { if (animated && (openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150)) { animated = false; @@ -13643,6 +14394,76 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private void updateSearchUpDownButtonVisibility(boolean animated) { + if (searchUpButton == null || searchDownButton == null) { + return; + } + boolean show = !getMediaDataController().searchResultMessages.isEmpty() && searching && !searchingFiltered; + if (show) { + if (searchUpButton.getTag() == null) { + if (searchUpButtonAnimation != null) { + searchUpButtonAnimation.removeAllListeners(); + searchUpButtonAnimation.cancel(); + searchUpButtonAnimation = null; + } + if (animated) { + searchUpButton.setVisibility(View.VISIBLE); + searchDownButton.setVisibility(View.VISIBLE); + searchUpButton.setTag(1); + searchUpButtonAnimation = ValueAnimator.ofFloat(searchUpDownEnterProgress, 1f); + searchUpButtonAnimation.addUpdateListener(valueAnimator -> { + searchUpDownEnterProgress = (float) valueAnimator.getAnimatedValue(); + contentView.invalidate(); + }); + searchUpButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + searchUpDownEnterProgress = 1f; + contentView.invalidate(); + } + }); + searchUpButtonAnimation.setDuration(200); + searchUpButtonAnimation.start(); + } else { + searchUpDownEnterProgress = 1f; + contentView.invalidate(); + } + } + } else { + returnToMessageId = 0; + if (searchUpButton.getTag() != null) { + searchUpButton.setTag(null); + if (searchUpButtonAnimation != null) { + searchUpButtonAnimation.removeAllListeners(); + searchUpButtonAnimation.cancel(); + searchUpButtonAnimation = null; + } + if (animated) { + searchUpButtonAnimation = ValueAnimator.ofFloat(searchUpDownEnterProgress, 0f); + searchUpButtonAnimation.addUpdateListener(valueAnimator -> { + searchUpDownEnterProgress = (float) valueAnimator.getAnimatedValue(); + contentView.invalidate(); + }); + searchUpButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + searchUpDownEnterProgress = 0f; + searchUpButton.setVisibility(View.INVISIBLE); + searchDownButton.setVisibility(View.INVISIBLE); + contentView.invalidate(); + } + }); + searchUpButtonAnimation.setDuration(200); + searchUpButtonAnimation.start(); + } else { + searchUpDownEnterProgress = 0f; + searchUpButton.setVisibility(View.INVISIBLE); + searchDownButton.setVisibility(View.INVISIBLE); + } + } + } + } + private void showMentionDownButton(boolean show, boolean animated) { if (mentiondownButton == null) { return; @@ -13757,6 +14578,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setNonNoveTranslation(y); } else { actionBar.setTranslationY(y); + if (tagSelector != null) { + tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); + } + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.setTranslationY(y); + } + if (savedMessagesHint != null) { + savedMessagesHint.setTranslationY(y); + } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(y); } @@ -13800,7 +14630,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected boolean heightAnimationEnabled() { INavigationLayout actionBarLayout = getParentLayout(); - if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { + if (isInsideContainer || inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { return false; } if (System.currentTimeMillis() - activityResumeTime < 250) { @@ -13896,7 +14726,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (parentLayout != null && parentLayout.isSheet()) { + if (isInsideContainer) { + adjustPanLayoutHelper.setResizableView(contentView); + } else if (parentLayout != null && parentLayout.isSheet()) { adjustPanLayoutHelper.setResizableView((FrameLayout) parentLayout.getView().getParent().getParent().getParent().getParent()); } adjustPanLayoutHelper.onAttach(); @@ -14036,7 +14868,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView || child == emojiHintTextView || child == undoView || child == topUndoView)) { + if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == searchUpButton || child == searchDownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView || child == emojiHintTextView || child == undoView || child == topUndoView)) { return false; } if (child == fragmentContextView && fragmentContextView.isCallStyle()) { @@ -14230,6 +15062,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (scrimView != null ? scrimViewAlpha : 1f))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } + + if (scrimViewReaction != null && scrimViewReactionAnimated) { + invalidate(); + } + if (scrimView != null) { if (scrimView == reactionsMentiondownButton || scrimView == mentiondownButton) { if (scrimViewAlpha < 1f) { @@ -14387,7 +15224,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawCaptionAfter.add(cell); } } - if (scrimViewReaction != null && cell != null) { + if (scrimViewReaction != null && cell != null && scrimGroup == null) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); @@ -14420,6 +15257,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } drawNamesAfter.clear(); } + if (scrimViewReaction != null && scrimGroup != null) { + scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + } size = drawCaptionAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { @@ -14469,6 +15310,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (topUndoView != null && topUndoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, topUndoView, SystemClock.uptimeMillis()); } + if (savedMessagesTagHint != null && savedMessagesTagHint.getVisibility() == View.VISIBLE) { + super.drawChild(canvas, savedMessagesTagHint, SystemClock.uptimeMillis()); + } } if (fixedKeyboardHeight > 0 && keyboardHeight < AndroidUtilities.dp(20)) { @@ -14523,9 +15367,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (lastWidth != widthSize) { globalIgnoreLayout = false; lastWidth = widthMeasureSpec; - if (chatMode == MODE_SAVED) { - showSearchAsIcon = false; - } else if (!inPreviewMode && currentUser != null && currentUser.self) { + if (!inPreviewMode && currentUser != null && currentUser.self) { SimpleTextView textView = avatarContainer.getTitleTextView(); int textWidth = (int) textView.getPaint().measureText(textView.getText(), 0, textView.getText().length()); if (widthSize - AndroidUtilities.dp(96 + 56) > textWidth + AndroidUtilities.dp(10)) { @@ -14538,7 +15380,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (showSearchAsIcon || showAudioCallAsIcon) { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { - ((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(96); + ((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(chatMode == MODE_SAVED ? 40 : 96); } } else { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { @@ -14659,7 +15501,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not child.measure(contentWidthSpec, contentHeightSpec); } else if (child == blurredView) { int h = allHeight; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); @@ -14668,7 +15510,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (child == chatListView || child == chatListThanosEffect) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + blurredViewTopOffset + blurredViewBottomOffset; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } if (bottomOverlay != null && bottomOverlay.getVisibility() == View.VISIBLE && bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() != View.GONE) { @@ -14690,7 +15532,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not child.measure(contentWidthSpec, contentHeightSpec); } else if (child == messagesSearchListView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); - int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - actionBarHeight - AndroidUtilities.dp(48), View.MeasureSpec.EXACTLY); + int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - (isInsideContainer ? 0 : actionBarHeight) - AndroidUtilities.dp(48), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (chatActivityEnterView.isPopupView(child)) { int height = chatActivityEnterView.getPopupViewHeight(child); @@ -14752,7 +15594,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (child == textSelectionHelper.getOverlayView(getContext())) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; textSelectionHelper.setKeyboardSize(keyboardSize); } else { @@ -14762,7 +15604,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (child instanceof MessagePreviewView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = allHeight - AndroidUtilities.statusBarHeight; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY); @@ -14798,6 +15640,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.requestLayout(); } + @Override + public int getKeyboardHeight() { + if (isInsideContainer) return 0; + return super.getKeyboardHeight(); + } + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); @@ -14870,7 +15718,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (child == mentionContainer) { childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); - } else if (child == pagedownButton || child == mentiondownButton || child == reactionsMentiondownButton) { + } else if (child == pagedownButton || child == searchUpButton || child == searchDownButton || child == mentiondownButton || child == reactionsMentiondownButton) { if (!inPreviewMode) { childTop -= chatActivityEnterView.getMeasuredHeight(); } @@ -14934,6 +15782,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void setNonNoveTranslation(float y) { contentView.setTranslationY(y); actionBar.setTranslationY(0); + if (tagSelector != null) { + tagSelector.setTranslationY((actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); + } + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.setTranslationY(0); + } + if (savedMessagesHint != null) { + savedMessagesHint.setTranslationY(0); + } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(0); } @@ -15021,7 +15878,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not suggestEmojiPanel.forceClose(); } } else { - createEmptyView(); + createEmptyView(false); if (currentEncryptedChat == null || bigEmptyView == null) { bottomOverlay.setVisibility(View.INVISIBLE); if (suggestEmojiPanel != null && chatActivityEnterView != null && chatActivityEnterView.hasText()) { @@ -15676,16 +16533,51 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateSelectedMessageReactions() { - List selected = new ArrayList<>(); - SparseArray objs = selectedMessagesIds[0]; - for (int i = 0; i < objs.size(); i++) { - selected.add(objs.valueAt(i)); + if (getDialogId() == getUserConfig().getClientUserId()) { + ArrayList messageObjects = new ArrayList<>(); + for (int a = 0; a < selectedMessagesIds.length; ++a) { + for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { + MessageObject messageObject = selectedMessagesIds[a].valueAt(k); + if (messageObject.hasValidGroupId()) { + MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); + MessageObject.GroupedMessagePosition position = group != null ? group.getPosition(messageObject) : null; + if (position == null || !position.last) { + continue; + } + } + messageObjects.add(messageObject); + } + } + boolean hasReactions = false; + if (tagSelector != null) { + tagSelector.setSelectedReactionsInclusive(messageObjects); + hasReactions = !tagSelector.getSelectedReactions().isEmpty(); + tagSelector.setHint(LocaleController.getString(!hasReactions ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); + AndroidUtilities.runOnUIThread(() -> { + if (tagSelector != null) { + tagSelector.requestLayout(); + } + }, 120); + } else { + hasReactions = !ReactionsContainerLayout.getInclusiveReactions(messageObjects).isEmpty(); + } + ActionBarMenuItem tagItem = actionBar.createActionMode().getItem(tag_message); + if (tagItem != null) { + tagItem.setIcon(hasReactions ? R.drawable.menu_tag_edit : R.drawable.menu_tag_plus, true); + } } - objs = selectedMessagesIds[1]; - for (int i = 0; i < objs.size(); i++) { - selected.add(objs.valueAt(i)); + if (selectionReactionsOverlay != null) { + List selected = new ArrayList<>(); + SparseArray objs = selectedMessagesIds[0]; + for (int i = 0; i < objs.size(); i++) { + selected.add(objs.valueAt(i)); + } + objs = selectedMessagesIds[1]; + for (int i = 0; i < objs.size(); i++) { + selected.add(objs.valueAt(i)); + } + selectionReactionsOverlay.setSelectedMessages(selected); } - selectionReactionsOverlay.setSelectedMessages(selected); } private void processRowSelect(View view, boolean outside, float touchX, float touchY) { @@ -16460,6 +17352,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int mode = (Integer) args[14]; boolean isCache = (Boolean) args[3]; boolean postponedScroll = postponedScrollToLastMessageQueryIndex > 0 && queryLoadIndex == postponedScrollToLastMessageQueryIndex; + boolean fakePostponedScroll = this.fakePostponedScroll; + this.fakePostponedScroll = false; if (postponedScroll) { postponedScrollToLastMessageQueryIndex = 0; } @@ -16483,7 +17377,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showProgressView(false); checkDispatchHideSkeletons(true); if (chatListView != null) { - createEmptyView(); + createEmptyView(false); if (!fragmentOpened) { chatListView.setAnimateEmptyView(false, 1); chatListView.setEmptyView(emptyViewContainer); @@ -16501,7 +17395,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragmentTransitionRunnable.run(); return; } - if (chatMode != mode && chatMode != MODE_SAVED) { + if (chatMode != mode && (chatMode != MODE_SAVED || getSavedDialogId() == getUserConfig().getClientUserId())) { if (chatMode != MODE_SCHEDULED) { if (isTopic) { ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); @@ -16544,8 +17438,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; oldMessagesDict = messagesDict[0].clone(); - clearChatData(); - if (chatMode == 0) { + clearChatData(!fakePostponedScroll); + if (chatMode == 0 || chatMode == MODE_SAVED) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -16602,7 +17496,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (postponedScrollMessageId == 0) { - clearChatData(); + clearChatData(true); } else { if (showScrollToMessageError) { boolean found = false; @@ -16635,8 +17529,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; - clearChatData(); - if (chatMode == 0) { + clearChatData(!fakePostponedScroll); + if (chatMode == 0 || chatMode == MODE_SAVED) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -16724,6 +17618,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!forwardEndReached[loadIndex]) { messages.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 0; a < 2; a++) { @@ -16971,6 +17866,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); + messagesByDaysSorted.put(obj.dateKeyInt, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { @@ -16986,6 +17882,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); if (chatMode == MODE_SCHEDULED && obj.messageOwner.date == 0x7ffffffe) { dateMsg.date = 0x7ffffffe; @@ -16997,7 +17895,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = getStableIdForDateObject(dateMsg.date); + dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); if (load_type == 1) { messages.add(0, dateObj); } else { @@ -17072,6 +17970,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newRowsCount++; dayArray.add(obj); + if (oldMessage == null && filteredMessagesDict != null) { + oldMessage = filteredMessagesDict.get(obj.getId()); + } if (oldMessage != null) { obj.copyStableParams(oldMessage); } else { @@ -17128,7 +18029,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrolledToUnread = true; newRowsCount++; } - } else if ((load_type == 3 || load_type == 4) && (startLoadFromMessageId < 0 && messageId == startLoadFromMessageId || startLoadFromMessageId > 0 && messageId > 0 && messageId <= startLoadFromMessageId)) { + } else if ((load_type == 3 || load_type == 4) && (startLoadFromMessageId < 0 && messageId == startLoadFromMessageId || startLoadFromMessageId > 0 && messageId > 0 && messageId <= startLoadFromMessageId) && !fakePostponedScroll) { removeSelectedMessageHighlight(); if (needSelectFromMessageId && messageId == startLoadFromMessageId) { highlightMessageId = messageId; @@ -17190,11 +18091,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; - chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); + if (!chatAdapter.isFiltered) { + chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); + } } startLoadFromMessageId = 0; } - if (newRowsCount > 0) { + if (newRowsCount > 0 && !chatAdapter.isFiltered) { int top = 0; MessageObject scrollToMessageObject = null; for (int i = 0; i < chatListView.getChildCount(); i++) { @@ -17242,7 +18145,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not loadSendAsPeers(fragmentBeginToShow); if (chatListView != null && chatScrollHelper != null) { - if (first || scrollToTopOnResume || forceScrollToTop) { + if (chatAdapter.isFiltered) { + scrollToMessagePosition = -10000; + scrollToMessage = null; + } else if (first || scrollToTopOnResume || forceScrollToTop) { forceScrollToTop = false; if (!postponedScroll) { chatAdapter.notifyDataSetChanged(true); @@ -17299,7 +18205,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } scrollToMessagePosition = -10000; scrollToMessage = null; - } else { + } else if (!fakePostponedScroll) { addSponsoredMessages(!isFirstLoading); moveScrollToLastMessage(true); } @@ -17364,7 +18270,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (first) { if (chatListView != null) { AndroidUtilities.runOnUIThread(() -> { - createEmptyView(); + createEmptyView(false); if (!fragmentBeginToShow) { chatListView.setAnimateEmptyView(false, 0); chatListView.setEmptyView(emptyViewContainer); @@ -17386,7 +18292,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0; a < newGroups.size(); a++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); groupedMessages.calculate(); - if (chatAdapter != null && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { + if (chatAdapter != null && !chatAdapter.isFiltered && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int idx = messages.indexOf(messageObject); if (idx >= 0) { @@ -17455,10 +18361,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not addSponsoredMessages(!isFirstLoading); checkScrollForLoad(false); - if (postponedScroll) { + if (postponedScroll && !fakePostponedScroll) { chatAdapter.notifyDataSetChanged(true); if (progressDialog != null) { progressDialog.dismiss(); + showMessagesSearchListView(false); } resetProgressDialogLoading(); updatePinnedListButton(false); @@ -17538,6 +18445,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkNewMessagesOnQuoteEdit(true); invalidatePremiumBlocked(); + + if (fakePostponedScroll) { + setFilterMessages(false, true, true); + } } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); @@ -17873,6 +18784,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); + messagesByDaysSorted.remove(obj.dateKeyInt); if (b >= 0 && b < messages.size()) { messages.remove(b); b--; @@ -17960,6 +18872,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); + messagesByDaysSorted.remove(obj.dateKeyInt); if (index >= 0 && index < messages.size()) { messages.remove(index); } @@ -18293,11 +19206,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; if (dialog_id == did) { + setFilterMessages(false); if (threadMessageId != 0) { if (forwardEndReached[0]) { forwardEndReached[0] = false; hideForwardEndReached = false; - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemInserted(0); } } @@ -18626,6 +19540,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not long did = (Long) args[0]; doOnIdle(() -> { int msgId = (Integer) args[1]; + if (filteredMessagesDict != null) { + MessageObject messageObject = filteredMessagesDict.get(msgId); + if (messageObject != null) { + MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); + messageObject.forceUpdate = true; + messageObject.reactionsChanged = true; + } + } MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); @@ -18634,6 +19556,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateMessageAnimated(messageObject, true); } }); + } else if (id == NotificationCenter.savedReactionTagsUpdate) { + if (dialog_id != getUserConfig().getClientUserId()) { + return; + } + long topicId = (long) args[0]; + if (topicId != 0 && topicId != getSavedDialogId()) { + return; + } + doOnIdle(() -> { + AndroidUtilities.forEachViews(chatListView, view -> { + if (view instanceof ChatMessageCell) { + MessageObject message = ((ChatMessageCell) view).getMessageObject(); + if (message != null) { + message.forceUpdate = true; + message.reactionsChanged = true; + } + } + }); + chatAdapter.notifyDataSetChanged(true); + }); } else if (id == NotificationCenter.didVerifyMessagesStickers) { ArrayList messages = (ArrayList) args[0]; for (int a = 0, N = messages.size(); a < N; a++) { @@ -18683,10 +19625,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } groupedMessages.calculate(); int index = messages.indexOf(messageObject); - if (index >= 0) { - if (chatAdapter != null) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); - } + if (chatAdapter != null && !chatAdapter.isFiltered && index >= 0) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); } } } @@ -19111,45 +20051,54 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.chatSearchResultsAvailable) { if (classGuid == (Integer) args[0]) { + updateSearchUpDownButtonVisibility(true); boolean jumpToMessage = (Boolean) args[6]; + updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (jumpToMessage) { int messageId = (Integer) args[1]; long did = (Long) args[3]; -// if (searchingReaction != null) { -// if (chatAdapter.isFiltered) { -// updateFilteredMessages(); -// } else { -// setFilterMessages(true); -// } -// } else - if (messageId != 0) { + if (searchingReaction != null && searchingFiltered) { + if (chatAdapter.isFiltered) { + updateFilteredMessages(true); + } else { + setFilterMessages(true); + } + } else if (messageId != 0) { + final boolean wasFiltered = chatAdapter.isFiltered; setFilterMessages(false); - scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); + if (!wasFiltered) { + scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); + } else { + updateVisibleRows(); + } } else { setFilterMessages(false); updateVisibleRows(); } - updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (searchItem != null) { searchItem.setShowSearchProgress(false); } + onSearchLoadingUpdate(false); + } else if (searchingReaction != null) { + if (chatAdapter.isFiltered) { + updateFilteredMessages(true); + } else { + setFilterMessages(true); + } } -// else if (searchingReaction != null) { -// if (chatAdapter.isFiltered) { -// updateFilteredMessages(); -// } else { -// setFilterMessages(true); -// } -// } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } + if (chatAdapter.isFiltered) { + AndroidUtilities.runOnUIThread(() -> checkScrollForLoad(false)); + } } } else if (id == NotificationCenter.chatSearchResultsLoading) { if (classGuid == (Integer) args[0]) { if (searchItem != null) { searchItem.setShowSearchProgress(true); } + onSearchLoadingUpdate(true); if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } @@ -19282,13 +20231,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!groupedMessages.messages.isEmpty()) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); - if (index >= 0) { + if (index >= 0 && !chatAdapter.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } } - if (updatedRows != null) { + if (updatedRows != null && !chatAdapter.isFiltered) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } @@ -19764,16 +20713,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else if (id == NotificationCenter.savedMessagesDialogsUpdate) { - if (checkedSavedMessagesHint && !savedMessagesHintShown && chatMode == 0 && savedMessagesHint != null && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { - savedMessagesHint.show(); - savedMessagesHintShown = true; - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1).apply(); - } - + checkSavedMessagesHint(); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } - + if (savedChatsItem != null && savedChatsGap != null) { + savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + } if (chatMode == MODE_SAVED && !isInsideContainer && getUserConfig().getClientUserId() != getSavedDialogId() && !getMessagesController().getSavedMessagesController().containsDialog(getSavedDialogId())) { finishFragment(); } @@ -20117,12 +21064,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); - if (index >= 0) { + if (index >= 0 && !chatAdapter.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } - if (updatedRows != null) { + if (updatedRows != null && !chatAdapter.isFiltered) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } @@ -20173,6 +21120,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messages.clear(); waitingForLoad.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 1; a >= 0; a--) { @@ -20202,7 +21150,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (progressView != null) { showProgressView(false); - createEmptyView(); + createEmptyView(false); chatListView.setEmptyView(emptyViewContainer); } @@ -20652,6 +21600,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dayArr.remove(removed); if (dayArr.isEmpty()) { messagesByDays.remove(removed.dateKey); + messagesByDaysSorted.remove(removed.dateKeyInt); if (index >= 0 && index < messages.size()) { messages.remove(index); } @@ -20851,6 +21800,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); + messagesByDaysSorted.put(obj.dateKeyInt, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { @@ -20866,12 +21816,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = getStableIdForDateObject(dateMsg.date); + dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); messages.add(placeToPaste, dateObj); if (chatAdapter != null) { chatAdapter.notifyItemInserted(placeToPaste); @@ -21063,6 +22015,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not processNewMessages(notPushedSponsoredMessages); } invalidatePremiumBlocked(); + + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } private int getStableIdForDateObject(int date) { @@ -21079,24 +22035,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } int top = 0; - MessageObject scrollToMessageObject = null; + int position = RecyclerListView.NO_POSITION; for (int i = 0; i < chatListView.getChildCount(); i++) { View v = chatListView.getChildAt(i); + final int vposition = chatListView.getChildAdapterPosition(v); + if (vposition < 0) continue; if (v instanceof ChatMessageCell) { - scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); + position = vposition; top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { - scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); + position = vposition; top = getScrollingOffsetForView(v); break; } } - if (scrollToMessageObject != null) { - int scrollToIndex = messages.indexOf(scrollToMessageObject); - if (scrollToIndex > 0) { -// chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top); - } + if (position >= 0) { + chatLayoutManager.scrollToPositionWithOffset(position, top); } } @@ -21159,7 +22114,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int commentsDeleted = 0; for (int a = 0; a < size; a++) { Integer mid = markAsDeletedMessages.get(a); - MessageObject obj = messagesDict[loadIndex].get(mid); + MessageObject obj = chatAdapter.isFiltered ? filteredMessagesDict.get(mid) : messagesDict[loadIndex].get(mid); if (selectedObject != null && obj == selectedObject || obj != null && selectedObjectGroup != null && selectedObjectGroup == groupedMessagesMap.get(obj.getGroupId())) { closeMenu(); } @@ -21205,7 +22160,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (editingMessageObject == obj) { hideFieldPanel(true); } - int index = messages.indexOf(obj); + int index = chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); if (index != -1) { if (obj.scheduled) { scheduledMessagesCount--; @@ -21215,8 +22170,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); } - MessageObject removed = messages.remove(index); + MessageObject removed = chatAdapter.getMessages().remove(index); if (chatAdapter != null) { + if (chatAdapter.isFiltered) { + int mindex = messages.indexOf(obj); + if (mindex >= 0) { + messages.remove(mindex); + } + getMediaDataController().removeMessageFromResults(removed.getId()); + } else if (filteredMessagesDict != null) { + MessageObject msg = filteredMessagesDict.get(mid); + if (msg != null) { + filteredMessagesDict.remove(mid); + chatAdapter.filteredMessages.remove(msg); + getMediaDataController().removeMessageFromResults(msg.getId()); + } + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } removedIndexes.add(chatAdapter.messagesStartRow + index); if (!sent && !obj.scheduledSent && removed != null && removed.messageOwner != null && removed.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT && currentTime - removed.messageOwner.date >= (currentChat != null || currentUser != null && currentUser.bot ? 2 : 0)) { thanosMessagesIndexes.add(chatAdapter.messagesStartRow + index); @@ -21243,10 +22215,35 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); - if (index < messages.size()) { - messages.remove(index); - if (chatAdapter != null) { - removedIndexes.add(chatAdapter.messagesStartRow + index); + messagesByDaysSorted.remove(obj.dateKeyInt); + int dindex = index; + if (chatAdapter != null && chatAdapter.isFiltered) { + dindex = messages.indexOf(obj); + } + if (dindex >= 0 && dindex < messages.size()) { + messages.remove(dindex); + if (chatAdapter != null && !chatAdapter.isFiltered) { + removedIndexes.add(chatAdapter.messagesStartRow + dindex); + } + } + } + } + if (filteredMessagesByDays != null) { + dayArr = filteredMessagesByDays.get(obj.dateKeyInt); + if (dayArr != null) { + MessageObject mobj = chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; + dayArr.remove(mobj); + if (dayArr.isEmpty()) { + filteredMessagesByDays.remove(obj.dateKeyInt); + int dindex = index; + if (chatAdapter != null && !chatAdapter.isFiltered) { + dindex = chatAdapter.filteredMessages.indexOf(mobj); + } + if (chatAdapter != null && dindex >= 0 && dindex < chatAdapter.filteredMessages.size()) { + chatAdapter.filteredMessages.remove(dindex); + if (chatAdapter.isFiltered) { + removedIndexes.add(chatAdapter.messagesStartRow + dindex); + } } } } @@ -21284,7 +22281,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { groupedMessages.calculate(); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); - int index = messages.indexOf(messageObject); + int index = chatAdapter.getMessages().indexOf(messageObject); if (index >= 0) { if (chatAdapter != null) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); @@ -21295,7 +22292,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (messages.isEmpty()) { if (!endReached[0] && !loading) { - showProgressView(false); + if (!chatAdapter.isFiltered) { + showProgressView(false); + } if (chatListView != null) { chatListView.setEmptyView(null); } @@ -21343,7 +22342,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!isThreadChat() || messages.size() <= 3) { removeUnreadPlane(false); } - if (messages.isEmpty()) { + if (chatAdapter.getMessages().isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } @@ -21351,7 +22350,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAdapter.notifyItemRemoved(0); } } else { - chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, messages.size()); + chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, chatAdapter.getMessages().size()); } } updateVisibleRows(); @@ -21366,6 +22365,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateScheduledInterface(true); } invalidatePremiumBlocked(); + + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } private void replaceMessageObjects(ArrayList messageObjects, int loadIndex, boolean remove) { @@ -21479,8 +22482,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { groupedMessages.messages.set(idx, messageObject); MessageObject.GroupedMessagePosition oldPosition = groupedMessages.positions.remove(old); + groupedMessages.positionsArray.remove(old.getId()); if (oldPosition != null) { groupedMessages.positions.put(messageObject, oldPosition); + groupedMessages.positionsArray.put(messageObject.getId(), oldPosition); } if (newGroups == null) { newGroups = new LongSparseArray<>(); @@ -21496,7 +22501,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.type >= 0) { messageObject.copyStableParams(old); messages.set(index, messageObject); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { @@ -21504,23 +22509,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else { messages.remove(index); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { dayArr.remove(index2); if (dayArr.isEmpty()) { messagesByDays.remove(old.dateKey); + messagesByDaysSorted.remove(old.dateKeyInt); messages.remove(index); int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); - if (messages.isEmpty()) { - if (prevLoadingUpRow >= 0) { - chatAdapter.notifyItemRemoved(0); - } - if (prevLoadingDownRow >= 0) { - chatAdapter.notifyItemRemoved(0); + if (!chatAdapter.isFiltered) { + chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); + if (messages.isEmpty()) { + if (prevLoadingUpRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } + if (prevLoadingDownRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } } } } @@ -21659,22 +22667,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void updateSearchButtons(int mask, int num, int count) { if (searchUpButton != null) { - searchUpButton.setEnabled((mask & 1) != 0); - searchUpButton.setAlpha(searchUpButton.isEnabled() ? 1.0f : 0.5f); + searchUpButton.setEnabled((mask & (reversed ? 2 : 1)) != 0); + searchUpButtonArrow.setAlpha(searchUpButton.isEnabled() ? 1.0f : 0.5f); } if (searchDownButton != null) { - searchDownButton.setEnabled((mask & 2) != 0); - searchDownButton.setAlpha(searchDownButton.isEnabled() ? 1.0f : 0.5f); + searchDownButton.setEnabled((mask & (reversed ? 1 : 2)) != 0); + searchDownButtonArrow.setAlpha(searchDownButton.isEnabled() ? 1.0f : 0.5f); } if (searchCountText != null) { + boolean animated = !LocaleController.isRTL; if (count < 0) { - searchCountText.setCount("", 0, false); + searchCountText.setText("", animated); } else if (count == 0) { - searchCountText.setCount(LocaleController.getString("NoResult", R.string.NoResult), 0, false); + searchCountText.setText(LocaleController.getString(R.string.NoResult), animated); + } else if (searchingFiltered) { + searchCountText.setText(LocaleController.formatPluralString("TaggedMessages", count), animated); } else { - searchCountText.setCount(LocaleController.formatString("OfCounted", R.string.OfCounted, num + 1, count), num + 1, true); + searchCountText.setText(LocaleController.formatString(R.string.Of, num + 1, count), animated); } } + if (searchExpandList != null) { + searchExpandList.setClickable(count > 0); + searchExpandList.animate().alpha(count > 0 ? 1f : 0.5f).start(); + } } @Override @@ -21716,15 +22731,68 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (checkedSavedMessagesHint) return; checkedSavedMessagesHint = true; - if (!savedMessagesHintShown && savedMessagesHint != null && chatMode == 0 && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { - savedMessagesHint.show(); - savedMessagesHintShown = true; - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1).apply(); + if (!savedMessagesHintShown && chatMode == 0 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { + if (savedMessagesHint != null && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1) { + savedMessagesHint.show(); + savedMessagesHintShown = true; + MessagesController.getGlobalMainSettings().edit() + .putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1) + .putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1) + .apply(); + } else if (savedMessagesSearchHint != null && MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) < 1) { + savedMessagesSearchHint.show(); + savedMessagesHintShown = true; + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1).apply(); + } else { + checkSavedMessagesTagHint(); + } + } + } + + private long lastScrollTime; + private boolean savedMessagesTagHintShown; + private void checkSavedMessagesTagHint() { + if (savedMessagesTagHint == null || savedMessagesTagHint.shown() || savedMessagesTagHintShown || !checkedSavedMessagesHint) { + return; + } + if (savedMessagesTagHint != null && (messagesSearchListView == null || messagesSearchListView.getTag() == null) && System.currentTimeMillis() - lastScrollTime > 1800 && MessagesController.getGlobalMainSettings().getInt("savedsearchtaghint", 0) < 1) { + final int[] loc = new int[2]; + ChatMessageCell foundCell = null; + for (int i = chatListView.getChildCount() - 1; i >= 0; --i) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + if (cell.areTags() && !cell.reactionsLayoutInBubble.reactionButtons.isEmpty()) { + cell.getLocationInWindow(loc); + + final float y = loc[1] + cell.reactionsLayoutInBubble.y; + if (y >= dp(240) && y <= AndroidUtilities.displaySize.y - dp(25) - AndroidUtilities.navigationBarHeight) { + foundCell = cell; + break; + } + } + } + } + + if (foundCell != null) { + savedMessagesTagHintShown = true; + ReactionsLayoutInBubble.ReactionButton btn = foundCell.reactionsLayoutInBubble.reactionButtons.get(0); + foundCell.getLocationInWindow(loc); + savedMessagesTagHint.setTranslationY(loc[1] - savedMessagesTagHint.getTop() - dp(120) + foundCell.reactionsLayoutInBubble.y); + savedMessagesTagHint.setJointPx(0, -dp(16) + loc[0] + foundCell.reactionsLayoutInBubble.x + btn.width / 2f); + savedMessagesTagHint.show(); + + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); + } else { + AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); + AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); + } } } @Override public void onBecomeFullyHidden() { + hideTagSelector(); if (!getMessagesController().premiumFeaturesBlocked() && getMessagesController().transcribeAudioTrialWeeklyNumber <= 0 && !getMessagesController().didPressTranscribeButtonEnough() && !getUserConfig().isPremium() && messages != null) { for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); @@ -22131,6 +23199,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } bottomOverlayChatWaitsReply = false; bottomOverlayLinks = false; + boolean forceNoBottom = false; if (chatMode == MODE_DEFAULT && userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { bottomOverlayLinks = true; bottomOverlayChatText.setVisibility(View.GONE); @@ -22141,9 +23210,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showBottomOverlayProgress(false, false); } else if (chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { if (getSavedDialogId() == UserObject.ANONYMOUS) { - bottomOverlayChat.setVisibility(View.GONE); - chatActivityEnterView.setVisibility(View.INVISIBLE); - return; + forceNoBottom = true; } else { bottomOverlayChatText.setTag(null); bottomOverlayChatText.setText(LocaleController.getString(currentUser != null ? R.string.SavedOpenChat : (ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.SavedOpenChannel : R.string.SavedOpenGroup))); @@ -22280,7 +23347,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { bottomOverlayImage.setVisibility(View.INVISIBLE); } - if (inPreviewMode || isInsideContainer) { + if (inPreviewMode) { if (searchContainer != null) { searchContainer.setVisibility(View.INVISIBLE); } @@ -22355,7 +23422,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); searchContainer.setVisibility(View.INVISIBLE); - } + } }).start(); } } @@ -22397,7 +23464,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not muteItemGap.setVisibility(View.VISIBLE); } } - if (reportType >= 0) { + if (isInsideContainer || forceNoBottom) { + bottomOverlayChat.setVisibility(View.GONE); + chatActivityEnterView.setVisibility(View.GONE); + } else if (reportType >= 0) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || @@ -23680,7 +24750,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not addToContactsButton.setTag(1); addToContactsButton.setVisibility(View.VISIBLE); } else { - if (!user.contact && !user.self && !show) { + if (!user.contact && !UserObject.isService(user.id) && !user.self && !show) { createTopPanel(); if (topChatPanelView == null) { return; @@ -24210,6 +25280,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public void checkAdjustResize() { + if (isInsideContainer) return; if (reportType >= 0) { AndroidUtilities.requestAdjustNothing(getParentActivity(), classGuid); } else { @@ -24263,11 +25334,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (contentView != null) { contentView.onPause(); } - if (chatMode == 0) { + if (chatMode == 0 || chatMode == MODE_SAVED && getUserConfig().getClientUserId() == getSavedDialogId()) { CharSequence[] message = new CharSequence[]{ignoreDraft ? null : draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); long draftThreadId; - if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { + if (chatMode == MODE_SAVED) { + draftThreadId = 0; + } else if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { if (replyMessage.replyToForumTopic != null) { draftThreadId = replyMessage.replyToForumTopic.id; } else { @@ -24371,8 +25444,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private int appliedDraftDate; public void applyDraftMaybe(boolean canClear) { - if (chatActivityEnterView == null || chatMode != 0) { + if (chatActivityEnterView == null || chatMode != 0 && (chatMode != MODE_SAVED || getUserConfig().getClientUserId() != getSavedDialogId())) { return; } TLRPC.DraftMessage draftMessage = null; @@ -24384,11 +25458,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not draftMessage = pair.second; } } else { - draftMessage = getMediaDataController().getDraft(dialog_id, threadMessageId); + draftMessage = getMediaDataController().getDraft(dialog_id, chatMode == MODE_SAVED ? 0 : threadMessageId); } TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null; - if (chatActivityEnterView.getFieldText() == null) { + if (chatActivityEnterView.getFieldText() == null || chatMode == 0 && getUserConfig().getClientUserId() == getDialogId() && draftMessage != null && appliedDraftDate < draftMessage.date) { if (draftMessage != null) { + appliedDraftDate = draftMessage.date; chatActivityEnterView.setWebPage(null, !draftMessage.no_webpage); CharSequence message; if (!draftMessage.entities.isEmpty()) { @@ -24768,6 +25843,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.preventInput = false; } textSelectionHintWasShowed = false; + + if (tagSelector != null) { + hideTagSelector(); + } } private boolean createMenu(View v, boolean single, boolean listView, float x, float y) { @@ -25075,7 +26154,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else if (type == 1) { @@ -25127,7 +26206,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message)) && !(message != null && message.messageOwner != null && message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) { - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -25140,7 +26219,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else { @@ -25209,11 +26288,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_STOP_POLL_OR_QUIZ); icons.add(R.drawable.msg_pollstop); } - } else if (selectedObject.isMusic() && !noforwards) { + } else if (selectedObject.isMusic() && !noforwards && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); - } else if (selectedObject.isDocument() && !noforwards) { + } else if (selectedObject.isDocument() && !noforwards && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); @@ -25236,14 +26315,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } - } else if (selectedObject.isMusic()) { + } else if (selectedObject.isMusic() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); - } else if (selectedObject.getDocument() != null) { + } else if (selectedObject.getDocument() != null && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(OPTION_ADD_TO_GIFS); @@ -25267,7 +26346,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_language); - if (!noforwards) { + if (!noforwards && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); @@ -25279,7 +26358,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_theme); - if (!noforwards) { + if (!noforwards && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); @@ -25288,7 +26367,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_shareout); } } else if (type == 6 && !noforwards && !selectedObject.hasRevealedExtendedMedia()) { - if (!selectedObject.needDrawBluredPreview()) { + if (!selectedObject.needDrawBluredPreview() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY2); icons.add(R.drawable.msg_gallery); @@ -25400,7 +26479,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -25437,14 +26516,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); - } else if (selectedObject.isMusic()) { + } else if (selectedObject.isMusic() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); - } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { + } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); @@ -25490,7 +26569,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_callback); } } - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -25878,10 +26957,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not addGap = true; } else if (showPrivateMessageSeen) { MessagePrivateSeenView messagePrivateSeenView = new MessagePrivateSeenView(getContext(), message, () -> { - if (scrimPopupWindow != null) { - scrimPopupWindow.dismiss(false); - scrimPopupWindow = null; - } + closeMenu(true); }, themeDelegate); popupLayout.addView(messagePrivateSeenView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); addGap = true; @@ -26341,8 +27417,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (optionsView != null) { scrimPopupContainerLayout.addView(optionsView); } else { - reactionsLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_DEFAULT, ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); - if (isReactionsAvailable) { + final boolean tags = getUserConfig().getClientUserId() == getDialogId(); + reactionsLayout = new ReactionsContainerLayout(tags ? ReactionsContainerLayout.TYPE_TAGS : ReactionsContainerLayout.TYPE_DEFAULT, ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); + if (tags) { + reactionsLayout.setHint(getUserConfig().isPremium() ? LocaleController.getString(R.string.SavedTagReactionsHint2) : AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.SavedTagReactionsPremiumHint), Theme.key_windowBackgroundWhiteBlueText2, 0, () -> { + closeMenu(false); + PremiumFeatureBottomSheet sheet = new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true); + sheet.setDimBehind(false); + sheet.setOnHideListener(d -> { + dimBehindView(false); + }); + sheet.show(); + })); + } + if (isReactionsAvailable && (!tags || !getMessagesController().premiumFeaturesBlocked())) { int pad = 22; int sPad = 24; reactionsLayout.setPadding(AndroidUtilities.dp(4) + (LocaleController.isRTL ? 0 : sPad), AndroidUtilities.dp(4), AndroidUtilities.dp(4) + (LocaleController.isRTL ? sPad : 0), AndroidUtilities.dp(pad)); @@ -26351,7 +27439,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reactionsLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View v, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { - selectReaction(primaryMessage, finalReactionsLayout, v,0, 0, visibleReaction,false, longpress, addToRecent); + selectReaction(primaryMessage, finalReactionsLayout, v,0, 0, visibleReaction,false, longpress, addToRecent, false); } @Override @@ -26362,11 +27450,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20); + LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, (int) (52 + reactionsLayout.getTopOffset() / AndroidUtilities.density + pad), Gravity.RIGHT, 0, 50, 0, -20); scrimPopupContainerLayout.addView(reactionsLayout, params); scrimPopupContainerLayout.setReactionsLayout(reactionsLayout); scrimPopupContainerLayout.setClipChildren(false); - reactionsLayout.setMessage(message, chatInfo); + MessageObject messageWithReactions = message; + MessageObject.GroupedMessages group = getValidGroupedMessage(message); + if (group != null) { + messageWithReactions = group.findPrimaryMessageObject(); + } + reactionsLayout.setMessage(messageWithReactions, chatInfo); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { @@ -26541,22 +27634,28 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not totalHeight += keyboardHeight; } int popupY; + int minY = (int) (chatListView.getY() + dp(24)); + int maxY = totalHeight - height - dp(8); if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); - if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { + if (isInsideContainer) { + int[] location = new int[2]; + v.getLocationInWindow(location); + popupY = (int) (location[1] + y); + + chatListView.getLocationInWindow(location); + minY = dp(24); + maxY = Math.min(location[1] + chatListView.getMeasuredHeight(), AndroidUtilities.displaySize.y) - dp(8) - height; + } else if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { popupY += AndroidUtilities.dp(240) - height; } - if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { - popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); - } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { - popupY = totalHeight - height - AndroidUtilities.dp(8); - } + popupY = Utilities.clamp(popupY, maxY, minY); } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; - scrimPopupContainerLayout.setMaxHeight(totalHeight - popupY); + scrimPopupContainerLayout.setMaxHeight(maxY + height - popupY); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; Runnable showMenu = () -> { if (scrimPopupWindow == null || fragmentView == null || scrimPopupWindow.isShowing() || !AndroidUtilities.isActivityRunning(getParentActivity())) { @@ -26604,10 +27703,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not createActionMode(); final ActionBarMenu actionMode = actionBar.createActionMode(); - View item = actionMode.getItem(delete); - if (item != null) { - item.setVisibility(View.VISIBLE); - } + actionMode.setItemVisibility(delete, View.VISIBLE); createBottomMessagesActionButtons(); bottomMessagesActionContainer.setVisibility(View.VISIBLE); @@ -26666,18 +27762,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } - private void createEmptyView() { - if (emptyViewContainer != null || getContext() == null) { + private void createEmptyView(boolean recreate) { + if (emptyViewContainer != null && !recreate || getContext() == null) { return; } - emptyViewContainer = new FrameLayout(getContext()); - emptyViewContainer.setOnTouchListener((v, event) -> true); - emptyViewContainer.setVisibility(View.INVISIBLE); - contentView.addView(emptyViewContainer, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + if (emptyViewContainer == null) { + emptyViewContainer = new FrameLayout(getContext()); + emptyViewContainer.setOnTouchListener((v, event) -> true); + emptyViewContainer.setVisibility(View.INVISIBLE); + contentView.addView(emptyViewContainer, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + } else { + emptyViewContainer.removeAllViews(); + } int distance = getArguments().getInt("nearby_distance", -1); - if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked || userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { + if (chatAdapter.isFiltered) { + emptyView = new TextView(getContext()); + emptyView.setText(LocaleController.getString(R.string.NoFilteredMessages)); + emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + emptyView.setGravity(Gravity.CENTER); + emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); + emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); + emptyView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); + emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + } else if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked || userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setPremiumLock(userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium(), dialog_id); greetingsViewContainer.setListener((sticker) -> { @@ -26700,16 +27810,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not String emptyMessage = null; if (isThreadChat() && chatMode == 0) { if (isComments) { - emptyMessage = LocaleController.getString("NoComments", R.string.NoComments); + emptyMessage = LocaleController.getString(R.string.NoComments); } else { - emptyMessage = LocaleController.getString("NoReplies", R.string.NoReplies); + emptyMessage = LocaleController.getString(R.string.NoReplies); } } else if (chatMode == MODE_SCHEDULED) { - emptyMessage = LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages); + emptyMessage = LocaleController.getString(R.string.NoScheduledMessages); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { - emptyMessage = LocaleController.getString("GotAQuestion", R.string.GotAQuestion); + emptyMessage = LocaleController.getString(R.string.GotAQuestion); } else if (currentUser == null || currentUser.self || currentUser.deleted || userBlocked) { - emptyMessage = LocaleController.getString("NoMessages", R.string.NoMessages); + emptyMessage = LocaleController.getString(R.string.NoMessages); } if (emptyMessage == null) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); @@ -26727,7 +27837,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); - emptyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + emptyView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } @@ -26801,10 +27911,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - public void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, View fromView, float x, float y, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean fromDoubleTap, boolean bigEmoji, boolean addToRecent) { + public void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, View fromView, float x, float y, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean fromDoubleTap, boolean bigEmoji, boolean addToRecent, boolean withoutAnimation) { if (isInScheduleMode() || primaryMessage == null) { return; } + + if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium() && primaryMessage.messageOwner != null && (primaryMessage.messageOwner.reactions == null || (primaryMessage.messageOwner.reactions.reactions_as_tags || primaryMessage.messageOwner.reactions.results.isEmpty()))) { + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } ReactionsEffectOverlay.removeCurrent(false); int currentChosenReactions = primaryMessage.getChoosenReactions().size(); @@ -26837,6 +27952,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getSendMessagesHelper().sendReaction(primaryMessage, visibleReactions, added ? visibleReaction : null, bigEmoji, addToRecent, ChatActivity.this, updateReactionRunnable = new Runnable() { @Override public void run() { + if (withoutAnimation) { + return; + } if (updateReactionRunnable != null) { updateReactionRunnable = null; if (fromDoubleTap) { @@ -26867,11 +27985,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - if (fromDoubleTap) { + if (fromDoubleTap || withoutAnimation) { updateMessageAnimated(primaryMessage, true); updateReactionRunnable.run(); } - AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); + if (!withoutAnimation) { + AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); + } } @SuppressLint("NotifyDataSetChanged") @@ -26897,13 +28017,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAdapter.notifyDataSetChanged(true); } else { MessageObject messageInList = messagesDict[0].get(message.getId()); - int index = messages.indexOf(messageInList); if (updateReactions) { message.forceUpdate = true; message.reactionsChanged = true; } - if (index >= 0) { - chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + if (chatAdapter.isFiltered) { + MessageObject filteredMessage = filteredMessagesDict != null ? filteredMessagesDict.get(message.getId()) : null; + int index = chatAdapter.filteredMessages.indexOf(filteredMessage); + if (filteredMessage != null && updateReactions) { + filteredMessage.forceUpdate = true; + filteredMessage.reactionsChanged = true; + } + if (index >= 0) { + chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + } + } else { + int index = messages.indexOf(messageInList); + if (index >= 0) { + chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + } } } }); @@ -27885,9 +29017,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.finishFragment(); createUndoView(); if (undoView != null) { - if (dids.size() == 1) { - undoView.showWithAction(dids.get(0).dialogId, UndoView.ACTION_FWD_MESSAGES, fmessages.size()); - } else { + if (dids.size() == 1) { + if (!BulletinFactory.of(ChatActivity.this).showForwardedBulletinWithTag(dids.get(0).dialogId, fmessages.size())) { + undoView.showWithAction(dids.get(0).dialogId, UndoView.ACTION_FWD_MESSAGES, fmessages.size()); + } + } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, fmessages.size(), dids.size(), null, null); } } @@ -28010,6 +29144,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onBackPressed() { + Bulletin bulletin = Bulletin.getVisibleBulletin(); + if (bulletin != null && bulletin.getLayout() instanceof Bulletin.LottieLayoutWithReactions) { + ((Bulletin.LottieLayoutWithReactions) bulletin.getLayout()).hideReactionsDialog(); + bulletin.hide(); + return false; + } if (secretVoicePlayer != null && secretVoicePlayer.isShown()) { secretVoicePlayer.dismiss(); return false; @@ -28282,7 +29422,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); } - private void openSearchWithText(String text) { + public void openSearchWithText(String text) { + boolean delay = false; + if (savedMessagesHint != null && savedMessagesHint.shown()) { + savedMessagesHint.hide(); + delay = true; + } + if (savedMessagesSearchHint != null && savedMessagesSearchHint.shown()) { + savedMessagesSearchHint.hide(); + delay = true; + } + if (delay) { + AndroidUtilities.runOnUIThread(() -> openSearchWithText(text), 200); + return; + } if (!actionBar.isSearchFieldVisible()) { AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, false, 0.95f, true); if (headerItem != null) { @@ -28313,12 +29466,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchItem.openSearch(openSearchKeyboard); } } - if (text != null) { - if (searchItem != null) { - searchItem.setSearchFieldText(text, false); - } - getMediaDataController().searchMessagesInChat(text, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + if (searchItem != null) { + searchItem.setSearchFieldText(text, false); } + getMediaDataController().searchMessagesInChat(searchingQuery = (text == null ? "" : text), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(text), searchingReaction); updatePinnedMessageView(true); } @@ -28888,7 +30039,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } messages.remove(index); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } } @@ -29464,7 +30615,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } PhotoViewer.getInstance().openPhoto(arrayList, arrayList.indexOf(message), dialog_id, 0, getTopicId(),photoViewerProvider); } else { - PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); + PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); } hideHints(false); MediaController.getInstance().resetGoingToShowMessageObject(); @@ -29508,6 +30659,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Context mContext; private boolean isBot; private int rowCount; + private int hintRow = -5; private int botInfoRow = -5; private int botInfoEmptyRow = -5; private int loadingUpRow = -5; @@ -29515,6 +30667,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public int messagesStartRow; private int messagesEndRow; + public ArrayList getMessages() { + if (isFrozen) { + return frozenMessages; + } else if (isFiltered) { + return filteredMessages; + } else { + return ChatActivity.this.messages; + } + } + public boolean isFrozen; public ArrayList frozenMessages = new ArrayList<>(); @@ -29531,14 +30693,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void updateRowsSafe() { int prevRowCount = rowCount; int prevBotInfoRow = botInfoRow; + int prevHintRow = hintRow; int prevLoadingUpRow = loadingUpRow; int prevLoadingDownRow = loadingDownRow; int prevMessagesStartRow = messagesStartRow; int prevMessagesEndRow = messagesEndRow; updateRowsInternal(); if (prevRowCount != rowCount || prevBotInfoRow != botInfoRow || - prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || - prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow) { + prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || + prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow || + prevHintRow != hintRow + ) { notifyDataSetChanged(false); } } @@ -29553,6 +30718,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { messages = ChatActivity.this.messages; } + if (chatMode == MODE_SAVED && isInsideContainer) { + hintRow = rowCount++; + } else { + hintRow = -5; + } if (!messages.isEmpty()) { if (!isFiltered && (!forwardEndReached[0] || mergeDialogId != 0 && !forwardEndReached[1]) && !hideForwardEndReached) { loadingDownRow = rowCount++; @@ -29625,8 +30795,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return 2; } else if (position == loadingDownRow) { return 3; + } else if (position == hintRow) { + return 4; } - return 4; + return 5; } @Override @@ -29881,8 +31053,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didPressReplyMessage(ChatActionCell cell, int id) { - MessageObject messageObject = cell.getMessageObject(); - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); + Runnable scroll = () -> { + MessageObject messageObject = cell.getMessageObject(); + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); + }; + if (chatAdapter.isFiltered) { + setFilterMessages(false, true, true); + AndroidUtilities.runOnUIThread(scroll, 80); + } else { + scroll.run(); + } } @Override @@ -29943,6 +31123,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (position == loadingDownRow || position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; loadingCell.setProgressVisible(loadsCount > 1); + } else if (position == hintRow) { + ChatActionCell actionCell = (ChatActionCell) holder.itemView; + createHint2MessageObject(); + actionCell.setMessageObject(hint2MessageObject); + actionCell.setCustomText(LocaleController.getString(R.string.SavedMessagesProfileHint)); + actionCell.setAlpha(1.0f); + actionCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { @@ -29980,7 +31167,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int prevPosition; int nextPosition; if (groupedMessages != null) { - MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition pos = groupedMessages.getPosition(message); if (pos != null) { if (groupedMessages.isDocuments) { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; @@ -30385,6 +31572,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return 3; } } + if (position == hintRow) { + return 1; + } if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { @@ -30789,47 +31979,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - private float actionBarTagsT; - private ValueAnimator actionBarTagsAnimator; - private void showActionBarSearchTags(boolean show) { - if (actionBarSearchTags == null) return; - if (actionBarTagsAnimator != null) { - actionBarTagsAnimator.cancel(); - } - actionBarSearchTags.setVisibility(View.VISIBLE); - actionBarTagsAnimator = ValueAnimator.ofFloat(actionBarTagsT, show ? 1f : 0f); - actionBarTagsAnimator.addUpdateListener(valueAnimator1 -> { - actionBarTagsT = (float) valueAnimator1.getAnimatedValue(); - if (actionBarSearchTags != null) { - actionBarSearchTags.setBackgroundColor(actionBar.getBackgroundColor()); - actionBarSearchTags.setShown(actionBarTagsT); - } - }); - actionBarTagsAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); - actionBarTagsAnimator.setDuration(320); - actionBarTagsAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - actionBarTagsT = show ? 1f : 0f; - if (actionBarSearchTags != null) { - actionBarSearchTags.setBackgroundColor(actionBar.getBackgroundColor()); - actionBarSearchTags.setShown(actionBarTagsT); - if (!show) { - actionBarSearchTags.setVisibility(View.GONE); - } - } - - invalidateChatListViewTopPadding = true; - updateChatListViewTopPadding(); - } - }); - actionBarTagsAnimator.start(); - } - + boolean searchWas; private class SearchItemListener extends ActionBarMenuItem.ActionBarMenuItemSearchListener { - boolean searchWas; - @Override public boolean canCollapseSearch() { if (messagesSearchListView.getTag() != null) { @@ -30846,12 +31998,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionBarSearchTags.clear(); } searchingReaction = null; - showSearchShowOther(false); + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); setFilterMessages(false); } @Override public void onSearchCollapse() { + searching = false; + updatePagedownButtonVisibility(true); + updateSearchUpDownButtonVisibility(true); if (searchCalendarButton != null) { searchCalendarButton.setVisibility(View.VISIBLE); } @@ -30866,7 +32022,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionContainer.getAdapter().setSearchingMentions(false); searchingUserMessages = null; searchingChatMessages = null; - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString("SavedTagSearchHint", R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); searchItem.setSearchFieldCaption(null); AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 0.95f, true); if (editTextItem != null && editTextItem.getTag() != null) { @@ -30940,31 +32096,36 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not valueAnimator.start(); searchingReaction = null; - showSearchShowOther(false); + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); if (actionBarSearchTags != null) { actionBarSearchTags.clear(); + actionBarSearchTags.show(false); } - showActionBarSearchTags(false); setFilterMessages(false); } @Override public void onSearchExpand() { - if (threadMessageId != 0 || UserObject.isReplyUser(currentUser)) { + searching = true; + updatePagedownButtonVisibility(true); + updateSearchUpDownButtonVisibility(true); + if (threadMessageId != 0 && chatMode != MODE_SAVED || UserObject.isReplyUser(currentUser)) { openSearchWithText(null); } - if (!openSearchKeyboard) { - return; + if (openSearchKeyboard) { + saveKeyboardPositionBeforeTransition(); + if (!isInsideContainer) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + AndroidUtilities.runOnUIThread(() -> { + searchWas = false; + searchItem.getSearchField().requestFocus(); + AndroidUtilities.showKeyboard(searchItem.getSearchField()); + removeKeyboardPositionBeforeTransition(); + }, 500); + hideSendButtonHints(); } - saveKeyboardPositionBeforeTransition(); - AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); - AndroidUtilities.runOnUIThread(() -> { - searchWas = false; - searchItem.getSearchField().requestFocus(); - AndroidUtilities.showKeyboard(searchItem.getSearchField()); - removeKeyboardPositionBeforeTransition(); - }, 500); - hideSendButtonHints(); whiteActionBar = getDialogId() == getUserConfig().getClientUserId(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(searchAnimationProgress, 1f); @@ -30972,7 +32133,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); valueAnimator.setDuration(320); valueAnimator.start(); -// showActionBarSearchTags(actionBarSearchTags != null && actionBarSearchTags.hasFilters()); + if (actionBarSearchTags != null) { + actionBarSearchTags.show(!isInsideContainer && actionBarSearchTags != null && actionBarSearchTags.hasFilters()); + } } private float searchAnimationProgress; @@ -30983,7 +32146,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (whiteActionBar) { int color1 = getThemedColor(Theme.key_actionBarDefaultIcon); actionBar.setItemsColor(ColorUtils.blendARGB(color1, getThemedColor(Theme.key_actionBarActionModeDefaultIcon), searchAnimationProgress), false); - actionBar.setItemsColor(ColorUtils.blendARGB(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), searchAnimationProgress), true); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), true); color1 = getThemedColor(Theme.key_actionBarDefaultSelector); int color2 = getThemedColor(Theme.key_actionBarActionModeDefaultSelector); @@ -30993,7 +32156,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlackText), searchAnimationProgress), false); actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearchPlaceholder), getThemedColor(Theme.key_windowBackgroundWhiteGrayText), searchAnimationProgress), true); actionBar.setSearchCursorColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlueText), searchAnimationProgress)); - AndroidUtilities.setLightStatusBar(fragmentView, isLightStatusBar()); + + if (!isInsideContainer && getParentActivity() != null) { + AndroidUtilities.setLightStatusBar(getParentActivity().getWindow(), isLightStatusBar()); + } } if (fragmentView != null) { fragmentView.invalidate(); @@ -31004,7 +32170,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onSearchPressed(EditText editText) { searchWas = true; updateSearchButtons(0, 0, -1); - getMediaDataController().searchMessagesInChat(editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + getMediaDataController().searchMessagesInChat(searchingQuery = editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } @Override @@ -31029,7 +32195,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchingForUser = false; searchItem.setSearchFieldText("", true); } - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString("SavedTagSearchHint", R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); searchCalendarButton.setVisibility(View.VISIBLE); searchUserButton.setVisibility(View.VISIBLE); searchingUserMessages = null; @@ -31050,6 +32216,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return searchItemListener; } + private boolean isSupportedTags() { + return getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported && getUserConfig().isPremium(); + } + private ChatMessageCellDelegate chatMessageCellDelegate; private ChatMessageCellDelegate getChatMessageCellDelegate() { if (chatMessageCellDelegate == null) { @@ -31158,8 +32328,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not { includeStoryFromMessage = includeStory; } @Override public void dismissInternal() { - super.dismissInternal(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + super.dismissInternal(); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { fragmentView.requestLayout(); } @@ -31216,7 +32386,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (dids.size() == 1) { - undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count, topic, null, null); + if (dids.valueAt(0).id != getUserConfig().getClientUserId() || !BulletinFactory.of(ChatActivity.this).showForwardedBulletinWithTag(dids.valueAt(0).id, count)) { + undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count, topic, null, null); + } } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, count, dids.size(), null, null); } @@ -31256,7 +32428,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(messageObject, false) : null, false); return result; } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(messages, messageObject, mergeDialogId); + return MediaController.getInstance().setPlaylist(chatAdapter.getMessages(), messageObject, mergeDialogId, !chatAdapter.isFiltered, null); } return false; } @@ -31637,7 +32809,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - if (longpress) { + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } + if (getUserConfig().getClientUserId() == getDialogId() && cell.areTags() && !getUserConfig().isPremium()) { + if (longpress) return; + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } + if (longpress || cell.areTags() && (isInsideContainer || searchingReaction != null && searchingReaction.isSame(reaction.reaction))) { if (!ChatObject.isChannelAndNotMegaGroup(currentChat) || dialog_id >= 0) { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); FrameLayout scrimPopupContainerLayout = new FrameLayout(getParentActivity()) { @@ -31675,47 +32855,87 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }; scrimPopupContainerLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - Rect backgroundPaddings = new Rect(); - Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); - shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); - shadowDrawable2.getPadding(backgroundPaddings); - scrimPopupContainerLayout.setBackground(shadowDrawable2); - - ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction)); + final ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction)); if (button == null) { return; } + + Rect backgroundPaddings = new Rect(); + Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); + shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable2.getPadding(backgroundPaddings); + scrimPopupContainerLayout.setBackground(shadowDrawable2); + float bottom = cell.reactionsLayoutInBubble.y + button.y + AndroidUtilities.dp(28); float left = cell.reactionsLayoutInBubble.x + button.x; int[] loc = new int[2]; cell.getLocationInWindow(loc); - scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) - .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { - EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { - @Override - public void dismiss() { - super.dismiss(); - dimBehindView(false); - } - }; - alert.setCalcMandatoryInsets(isKeyboardVisible()); - alert.setDimBehind(false); - closeMenu(false); - showDialog(alert); - }) - .setOnProfileSelectedListener((view1, userId, messagePeerReaction) -> { - Bundle args = new Bundle(); - if (userId > 0) { - args.putLong("user_id", userId); - } else { - args.putLong("chat_id", -userId); - } - args.putInt("report_reaction_message_id", cell.getMessageObject().getId()); - args.putLong("report_reaction_from_dialog_id", dialog_id); - ProfileActivity fragment = new ProfileActivity(args); - presentFragment(fragment); + final boolean tags = getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported; + if (tags) { + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); + + ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), 0, getResourceProvider(), 0); + if (getUserConfig().isPremium()) { + ActionBarMenuSubItem editTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + editTag.setTextAndIcon(LocaleController.getString(TextUtils.isEmpty(getMessagesController().getSavedTagName(reaction.reaction)) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag), R.drawable.menu_tag_rename); + editTag.setMinimumWidth(160); + editTag.setOnClickListener(view -> { closeMenu(); - }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); + SearchTagsList.openRenameTagAlert(getContext(), currentAccount, reaction.reaction, themeDelegate, false); + }); + popupLayout.addView(editTag); + } + if (!isInsideContainer && (searchingReaction == null || !searchingReaction.isSame(reaction.reaction)) && (chatMode == 0 || chatMode == MODE_SAVED)) { + ActionBarMenuSubItem filterByTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + filterByTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagFilterByTag), R.drawable.menu_tag_filter); + filterByTag.setMinimumWidth(160); + filterByTag.setOnClickListener(view -> { + closeMenu(); + openSearchWithText(""); + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction), true); + } + }); + popupLayout.addView(filterByTag); + } + ActionBarMenuSubItem removeTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + removeTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagRemoveTag), R.drawable.menu_tag_delete); + removeTag.setMinimumWidth(160); + removeTag.setOnClickListener(view -> { + pressedReaction(cell, reaction); + }); + removeTag.setColors(Theme.getColor(Theme.key_color_red), Theme.getColor(Theme.key_color_red)); + popupLayout.addView(removeTag); + scrimPopupContainerLayout.addView(popupLayout); + } else { + scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) + .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { + EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { + @Override + public void dismiss() { + super.dismiss(); + dimBehindView(false); + } + }; + alert.setCalcMandatoryInsets(isKeyboardVisible()); + alert.setDimBehind(false); + closeMenu(false); + showDialog(alert); + }) + .setOnProfileSelectedListener((view1, userId, messagePeerReaction) -> { + Bundle args = new Bundle(); + if (userId > 0) { + args.putLong("user_id", userId); + } else { + args.putLong("chat_id", -userId); + } + args.putInt("report_reaction_message_id", cell.getMessageObject().getId()); + args.putLong("report_reaction_from_dialog_id", dialog_id); + ProfileActivity fragment = new ProfileActivity(args); + presentFragment(fragment); + closeMenu(); + }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); + } scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override @@ -31765,10 +32985,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int popupY; if (height < totalHeight) { - if (height < totalHeight / 2f && chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { - popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y - height); + float cellY = chatListView.getY() + cell.getY(); + if (isInsideContainer) { + int[] location = new int[2]; + cell.getLocationInWindow(location); + cellY = location[1]; + } + if (height < totalHeight / 2f && cellY + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { + popupY = (int) (cellY + cell.reactionsLayoutInBubble.y + button.y - height); } else { - popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y + button.height); + popupY = (int) (cellY + cell.reactionsLayoutInBubble.y + button.y + button.height); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; @@ -31777,7 +33003,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); - scrimViewReaction = reaction.reaction instanceof TLRPC.TL_reactionEmoji ? ((TLRPC.TL_reactionEmoji) reaction.reaction).emoticon : null; + scrimViewReaction = reaction.reaction.hashCode(); + scrimViewReactionAnimated = reaction.reaction instanceof TLRPC.TL_reactionCustomEmoji && LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD); dimBehindView(cell, true); hideHints(false); if (topUndoView != null) { @@ -31790,12 +33017,50 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.getEditField().setAllowDrawCursor(false); } } + } else if (cell.areTags() && (chatMode == 0 || chatMode == MODE_SAVED)) { + closeMenu(); + openSearchWithText(""); + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction), true); + } } else if (reaction != null) { - ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction); - selectReaction(cell.getPrimaryMessageObject(), null, null,0, 0, visibleReaction,false, false, false); + pressedReaction(cell, reaction); } } + private void pressedReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction); + MessageObject messageObject = cell.getPrimaryMessageObject(); + selectReaction(cell.getPrimaryMessageObject(), null, null, 0, 0, visibleReaction,false, false, false, false); + if (messageObject != null & messageObject.messageOwner != null) { + if (chatAdapter.isFiltered) { + MessageObject realMessage = messagesDict[0].get(messageObject.getId()); + if (realMessage != null && realMessage.messageOwner != null) { + realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; + } + } else if (!chatAdapter.isFiltered && searchingReaction != null) { + updateFilteredMessages(false); + } + } + if (chatAdapter.isFiltered && !cell.getPrimaryMessageObject().hasReaction(searchingReaction)) { + final MessageObject msg = cell.getPrimaryMessageObject(); + final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); + if (groupedMessages != null) { + for (int i = 0; i < groupedMessages.messages.size(); ++i) { + MessageObject gmsg = groupedMessages.messages.get(i); + getMediaDataController().removeMessageFromResults(gmsg.getId()); + } + } else { + getMediaDataController().removeMessageFromResults(msg.getId()); + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } + updateFilteredMessages(true); + } + } + + @Override public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { if (showCount >= 0 || buttons.isEmpty()) { @@ -31901,7 +33166,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Bundle args = new Bundle(); args.putLong("chat_id", chat.id); if (longPress) { - ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, getResourceProvider(), ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM); + ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext(), R.drawable.popup_fixed_alert, getResourceProvider(), ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM); previewMenu.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); ActionBarMenuSubItem openChannel = new ActionBarMenuSubItem(getParentActivity(), false, false); @@ -32127,7 +33392,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return; } - if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE) { + if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE || chatMode == MODE_SAVED && (messageObject.replyMessageObject == null || messageObject.replyMessageObject.getSavedDialogId() != getTopicId())) { if (LaunchActivity.instance != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(); @@ -32156,10 +33421,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not highlightMessageQuoteOffset = quoteOffset; showNoQuoteAlert = true; } - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { - progressDialogAtMessageId = messageObject.getId(); - progressDialogAtMessageType = PROGRESS_REPLY; - }); + Runnable scroll = () -> { + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { + progressDialogAtMessageId = messageObject.getId(); + progressDialogAtMessageType = PROGRESS_REPLY; + }); + }; + if (chatAdapter.isFiltered) { + setFilterMessages(searchingFiltered = false, true, false); + updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); + AndroidUtilities.runOnUIThread(scroll, 80); + } else { + scroll.run(); + } } } } @@ -32376,6 +33650,35 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; BoostDialogs.openGiveAwayStatusDialog(messageObject, progressDialogCurrent, getContext(), getResourceProvider()); + } else if (type == 21) { + if (ApplicationLoader.isStandaloneBuild()) { + if (LaunchActivity.instance != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }; + LaunchActivity.instance.checkAppUpdate(true, progressDialogCurrent); + } + } else if (BuildVars.isHuaweiStoreApp()){ + Browser.openUrl(getContext(), BuildVars.HUAWEI_STORE_URL); + } else { + Browser.openUrl(getContext(), BuildVars.PLAYSTORE_APP_URL); + } } else if (type == 8) { PollVotesAlert.showForPoll(ChatActivity.this, messageObject); } else if (type == 0) { @@ -32664,6 +33967,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return false; } + + @Override + public boolean doNotShowLoadingReply(MessageObject msg) { + return msg != null && msg.getDialogId() == UserObject.REPLY_BOT || (chatAdapter != null && chatAdapter.isFiltered); + } }; private void openUserProfile(long uid) { @@ -32813,6 +34121,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (threadId != 0 || topicId != 0 || commentId != 0) { return false; } else { + if (ChatObject.isForum(currentChat)) { + TLRPC.TL_forumTopic requestedForumTopic = getMessagesController().getTopicsController().findTopic(channelId, messageId); + if (requestedForumTopic != null) { + return forumTopic != null && forumTopic.id == requestedForumTopic.id; + } + } showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); @@ -33398,16 +34712,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(replyCloseImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_replyPanelClose)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_replyPanelName)); - themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); - themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); - themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); - themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); - themeDescriptions.add(new ThemeDescription(searchCountText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_searchPanelText)); - themeDescriptions.add(new ThemeDescription(searchAsListTogglerView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); @@ -33554,6 +34862,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return avatarContainer; } + public void openedInstantly() { + fragmentOpened = true; + fragmentBeginToShow = true; + fragmentTransition = null; + contentView.invalidate(); + contentView.setSkipBackgroundDrawing(false); + toPullingDownTransition = false; + fragmentView.setAlpha(1f); + avatarContainer.setTranslationY(0); + avatarContainer.getAvatarImageView().setScaleX(1f); + avatarContainer.getAvatarImageView().setScaleY(1f); + avatarContainer.getAvatarImageView().setAlpha(1f); + } + @Override public AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { if (isOpen && fromPullingDownTransition && getParentLayout() != null && getParentLayout().getFragmentStack().size() > 1) { @@ -34740,9 +36062,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public boolean supportsThanosEffect() { - if (chatListThanosEffect != null && chatListThanosEffect.destroyed) { - return false; - } return ThanosEffect.supports() && LiteMode.isEnabled(LiteMode.FLAG_CHAT_THANOS); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java index 531cecad6..0e004d6d3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java @@ -14,6 +14,7 @@ import android.widget.FrameLayout; import com.google.android.exoplayer2.util.Log; +import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; import org.telegram.ui.ActionBar.INavigationLayout; @@ -30,14 +31,27 @@ public class ChatActivityContainer extends FrameLayout { private final INavigationLayout parentLayout; private View fragmentView; - public ChatActivityContainer(Context context, INavigationLayout parentLayout, Bundle args) { + public ChatActivityContainer(Context context, Utilities.Callback0Return resizableView, INavigationLayout parentLayout, Bundle args) { super(context); this.parentLayout = parentLayout; - chatActivity = new ChatActivity(args); + chatActivity = new ChatActivity(args) { + @Override + public void setNavigationBarColor(int color) {} + + @Override + protected void onSearchLoadingUpdate(boolean loading) { + ChatActivityContainer.this.onSearchLoadingUpdate(loading); + } + }; + chatActivity.insideContainerResizableView = resizableView; chatActivity.isInsideContainer = true; } + protected void onSearchLoadingUpdate(boolean loading) { + + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -57,6 +71,7 @@ public class ChatActivityContainer extends FrameLayout { parent.removeView(fragmentView); } } + chatActivity.openedInstantly(); addView(fragmentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (isActive) { chatActivity.onResume(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java index 4808e6422..efa124fb1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java @@ -199,6 +199,7 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat infoCell.setText(ChatObject.isChannelAndNotMegaGroup(currentChat) ? LocaleController.getString("EnableReactionsChannelInfo", R.string.EnableReactionsChannelInfo) : LocaleController.getString("EnableReactionsGroupInfo", R.string.EnableReactionsGroupInfo)); } else { + infoCell.setForeground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); if (selectedType == SELECT_TYPE_SOME) { infoCell.setText(LocaleController.getString("EnableSomeReactionsInfo", R.string.EnableSomeReactionsInfo)); } else if (selectedType == SELECT_TYPE_ALL) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java index de2350010..d6230701e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java @@ -24,7 +24,7 @@ import org.telegram.ui.Components.SpeedIconDrawable; public class ChooseSpeedLayout { - ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout; + public ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout; ActionBarMenuSlider.SpeedSlider slider; private static final float MIN_SPEED = 0.2f; 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 ac5d2f099..4cb085afb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -604,7 +604,7 @@ public class AnimatedEmojiDrawable extends Drawable { imageReceiver.setLayerNum(6656); } imageReceiver.setAspectFit(true); - if (cacheType == CACHE_TYPE_RENDERING_VIDEO || cacheType == STANDARD_LOTTIE_FRAME || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { + if (cacheType == CACHE_TYPE_RENDERING_VIDEO || cacheType == CACHE_TYPE_SAVED_REACTION || cacheType == STANDARD_LOTTIE_FRAME || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { imageReceiver.setAllowStartAnimation(false); imageReceiver.setAllowStartLottieAnimation(false); imageReceiver.setAutoRepeat(0); @@ -628,7 +628,7 @@ public class AnimatedEmojiDrawable extends Drawable { imageReceiver.setAutoRepeatCount(2); } else if (cacheType == CACHE_TYPE_FORUM_TOPIC_LARGE || cacheType == CACHE_TYPE_SAVED_REACTION || cacheType == CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { imageReceiver.setAutoRepeatCount(1); - } else if (cacheType == CACHE_TYPE_EMOJI_CALL){ + } else if (cacheType == CACHE_TYPE_EMOJI_CALL) { imageReceiver.setAutoRepeatCount(0); } } 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 b6d091c5a..7de70b606 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.lerp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; @@ -93,6 +95,8 @@ public class AnimatedTextView extends View { private TimeInterpolator animateInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; private float moveAmplitude = 1f; + private float scaleAmplitude = 0; + private int alpha = 255; private final Rect bounds = new Rect(); @@ -163,8 +167,8 @@ public class AnimatedTextView extends View { int fullWidth = bounds.width(); int fullHeight = bounds.height(); if (currentParts != null && oldParts != null && t != 1) { - float width = AndroidUtilities.lerp(oldWidth, currentWidth, t); - float height = AndroidUtilities.lerp(oldHeight, currentHeight, t); + float width = lerp(oldWidth, currentWidth, t); + float height = lerp(oldHeight, currentHeight, t); canvas.translate(0, (fullHeight - height) / 2f); for (int i = 0; i < currentParts.length; ++i) { Part current = currentParts[i]; @@ -179,7 +183,7 @@ public class AnimatedTextView extends View { if (isRTL && !ignoreRTL) { oldX = oldWidth - (oldX + old.width); } - x = AndroidUtilities.lerp(oldX - old.left, x - current.left, t); + x = lerp(oldX - old.left, x - current.left, t); applyAlphaInternal(1f); } else { x -= current.left; @@ -198,6 +202,10 @@ public class AnimatedTextView extends View { } } canvas.translate(x, y); + if (j < 0 && scaleAmplitude > 0) { + final float s = lerp(1f - scaleAmplitude, 1f, t); + canvas.scale(s, s, current.width / 2f, current.layout.getHeight() / 2f); + } current.layout.draw(canvas); canvas.restore(); } @@ -225,6 +233,10 @@ public class AnimatedTextView extends View { } } canvas.translate(x, y); + if (scaleAmplitude > 0) { + final float s = lerp(1f, 1f - scaleAmplitude, t); + canvas.scale(s, s, old.width / 2f, old.layout.getHeight() / 2f); + } old.layout.draw(canvas); canvas.restore(); } @@ -249,7 +261,6 @@ public class AnimatedTextView extends View { x += fullWidth - currentWidth; } } -// boolean isAppeared = currentLayoutToOldIndex != null && i < currentLayoutToOldIndex.length && currentLayoutToOldIndex[i] < 0; canvas.translate(x, 0); current.layout.draw(canvas); canvas.restore(); @@ -445,7 +456,7 @@ public class AnimatedTextView extends View { public float getCurrentWidth() { if (currentParts != null && oldParts != null) { - return AndroidUtilities.lerp(oldWidth, currentWidth, t); + return lerp(oldWidth, currentWidth, t); } return currentWidth; } @@ -458,7 +469,7 @@ public class AnimatedTextView extends View { if (oldParts == null || otherTextDrawable.oldParts == null) { return Math.max(getCurrentWidth(), otherTextDrawable.getCurrentWidth()); } - return AndroidUtilities.lerp( + return lerp( Math.max(oldWidth, otherTextDrawable.oldWidth), Math.max(currentWidth, otherTextDrawable.currentWidth), Math.max(t, otherTextDrawable.t) @@ -865,6 +876,10 @@ public class AnimatedTextView extends View { animateInterpolator = interpolator; } + public void setScaleProperty(float scale) { + this.scaleAmplitude = scale; + } + public void copyStylesFrom(TextPaint paint) { setTextColor(paint.getColor()); setTextSize(paint.getTextSize()); @@ -913,7 +928,7 @@ public class AnimatedTextView extends View { } public float isNotEmpty() { - return AndroidUtilities.lerp( + return lerp( oldText == null || oldText.length() <= 0 ? 0f : 1f, currentText == null || currentText.length() <= 0 ? 0f : 1f, oldText == null ? 1f : t @@ -1055,6 +1070,10 @@ public class AnimatedTextView extends View { drawable.setAnimationProperties(moveAmplitude, startDelay, duration, interpolator); } + public void setScaleProperty(float scale) { + drawable.setScaleProperty(scale); + } + public AnimatedTextDrawable getDrawable() { return drawable; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java index faba01cf2..108842449 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -80,6 +80,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.audioinfo.AudioInfo; import org.telegram.tgnet.TLRPC; @@ -457,6 +458,12 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. actionBar.setTitle(ContactsController.formatName(user.first_name, user.last_name)); } } + } else if (did == UserConfig.getInstance(currentAccount).getClientUserId()) { + if (messageObject.getSavedDialogId() == UserObject.ANONYMOUS) { + actionBar.setTitle(LocaleController.getString(R.string.AnonymousForward)); + } else { + actionBar.setTitle(LocaleController.getString(R.string.SavedMessages)); + } } else if (DialogObject.isUserDialog(did)) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); if (user != null) { 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 9c7dfcc4f..f53f8b54f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -349,6 +349,10 @@ public class BackupImageView extends View { invalidate(); } + public AnimatedEmojiDrawable getAnimatedEmojiDrawable() { + return animatedEmojiDrawable; + } + ValueAnimator roundRadiusAnimator; public void animateToRoundRadius(int animateToRad) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java index dd77a898d..eea05353f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java @@ -15,7 +15,7 @@ import org.telegram.messenger.SharedConfig; public class BlurredFrameLayout extends FrameLayout { - private final SizeNotifierFrameLayout sizeNotifierFrameLayout; + protected final SizeNotifierFrameLayout sizeNotifierFrameLayout; protected Paint backgroundPaint; public int backgroundColor = Color.TRANSPARENT; public int backgroundPaddingBottom; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java index 9dec20029..108459710 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -160,10 +160,10 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); actionBar.setCastShadows(true); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setTitle(getTitle()); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index ac623d3dd..287642198 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -22,10 +22,15 @@ import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.GestureDetector; @@ -57,14 +62,20 @@ import androidx.dynamicanimation.animation.SpringForce; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.support.SparseLongArray; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; +import org.telegram.ui.LaunchActivity; import java.lang.annotation.Retention; import java.util.ArrayList; @@ -1023,12 +1034,16 @@ public class Bulletin { private Matrix clipMatrix; private Paint clipPaint; + protected int getMeasuredBackgroundHeight() { + return getMeasuredHeight(); + } + @Override protected void dispatchDraw(Canvas canvas) { if (bulletin == null) { return; } - background.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom()); + background.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredBackgroundHeight() - getPaddingBottom()); if (isTransitionRunning() && delegate != null) { final float top = delegate.getTopOffset(bulletin.tag) - getY(); final float bottom = ((View) getParent()).getMeasuredHeight() - getBottomOffset() - getY(); @@ -1044,7 +1059,7 @@ public class Bulletin { if (clipPaint == null) { clipPaint = new Paint(Paint.ANTI_ALIAS_FLAG); clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - clipGradient = new LinearGradient(0, 0, 0, AndroidUtilities.dp(8), this.top ? new int[] {0xff000000, 0} : new int[] {0, 0xff000000}, new float[] { 0, 1 }, Shader.TileMode.CLAMP); + clipGradient = new LinearGradient(0, 0, 0, AndroidUtilities.dp(8), this.top ? new int[]{0xff000000, 0} : new int[]{0, 0xff000000}, new float[]{0, 1}, Shader.TileMode.CLAMP); clipMatrix = new Matrix(); clipGradient.setLocalMatrix(clipMatrix); clipPaint.setShader(clipGradient); @@ -1090,6 +1105,7 @@ public class Bulletin { } private boolean wrapWidth; + public void setWrapWidth() { wrapWidth = true; } @@ -1307,10 +1323,156 @@ public class Bulletin { } } + public static class LottieLayoutWithReactions extends LottieLayout implements NotificationCenter.NotificationCenterDelegate { + + private ReactionsContainerLayout reactionsContainerLayout; + private SparseLongArray newMessagesByIds; + private final BaseFragment fragment; + private final int messagesCount; + + public LottieLayoutWithReactions(BaseFragment fragment, int messagesCount) { + super(fragment.getContext(), fragment.getResourceProvider()); + this.fragment = fragment; + this.messagesCount = messagesCount; + init(); + } + + private Bulletin bulletin; + public void setBulletin(Bulletin b) { + this.bulletin = b; + } + + public void init() { + textView.setLayoutParams(LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.TOP, 56, 6, 8, 0)); + imageView.setLayoutParams(LayoutHelper.createFrameRelatively(56, 48, Gravity.START | Gravity.TOP)); + reactionsContainerLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_TAGS, fragment, getContext(), fragment.getCurrentAccount(), fragment.getResourceProvider()) { + @Override + protected void onShownCustomEmojiReactionDialog() { + Bulletin bulletin = Bulletin.getVisibleBulletin(); + if (bulletin != null) { + bulletin.setCanHide(false); + } + reactionsContainerLayout.getReactionsWindow().windowView.setOnClickListener(v -> { + hideReactionsDialog(); + Bulletin.hideVisible(); + }); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + if (bulletin != null) { + bulletin.setCanHide(false); + } + } else if (ev.getAction() == MotionEvent.ACTION_UP) { + if (bulletin != null) { + bulletin.setCanHide(true); + } + } + return super.dispatchTouchEvent(ev); + } + }; + reactionsContainerLayout.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(24), AndroidUtilities.dp(4), AndroidUtilities.dp(0)); + reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { + @Override + public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { + if (newMessagesByIds == null) { + return; + } + final long selfId = UserConfig.getInstance(fragment.getCurrentAccount()).getClientUserId(); + boolean isFragmentSavedMessages = fragment instanceof ChatActivity && ((ChatActivity) fragment).getDialogId() == selfId; + int lastMessageId = 0; + for (int i = 0; i < newMessagesByIds.size(); i++) { + int key = newMessagesByIds.keyAt(i); + TLRPC.Message message = new TLRPC.Message(); + message.dialog_id = fragment.getUserConfig().getClientUserId(); + message.id = key; + MessageObject messageObject = new MessageObject(fragment.getCurrentAccount(), message, false, false); + ArrayList visibleReactions = new ArrayList<>(); + visibleReactions.add(visibleReaction); + fragment.getSendMessagesHelper().sendReaction(messageObject, visibleReactions, visibleReaction, false, false, fragment, null); + lastMessageId = message.id; + } + hideReactionsDialog(); + Bulletin.hideVisible(); + showTaggedReactionToast(visibleReaction, fragment.getCurrentAccount(), lastMessageId, !isFragmentSavedMessages); + } + + private void showTaggedReactionToast(ReactionsLayoutInBubble.VisibleReaction visibleReaction, int currentAccount, int messageId, boolean addViewButton) { + AndroidUtilities.runOnUIThread(() -> { + BaseFragment baseFragment = LaunchActivity.getLastFragment(); + TLRPC.Document document; + if (visibleReaction.documentId == 0) { + TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(visibleReaction.emojicon); + if (availableReaction == null) { + return; + } + document = availableReaction.activate_animation; + } else { + document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, visibleReaction.documentId); + } + + if (document == null || baseFragment == null) { + return; + } + + BulletinFactory.of(baseFragment).createMessagesTaggedBulletin(messagesCount, document, addViewButton ? () -> { + Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putInt("message_id", messageId); + baseFragment.presentFragment(new ChatActivity(args)); + } : null).show(true); + }, 300); + } + }); + reactionsContainerLayout.setTop(true); + reactionsContainerLayout.setClipChildren(false); + reactionsContainerLayout.setClipToPadding(false); + reactionsContainerLayout.setVisibility(View.VISIBLE); + reactionsContainerLayout.setBubbleOffset(-AndroidUtilities.dp(80)); + reactionsContainerLayout.setHint(LocaleController.getString(R.string.SavedTagReactionsHint)); + addView(reactionsContainerLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL, 0, 36, 0, 0)); + reactionsContainerLayout.setMessage(null, null); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.savedMessagesForwarded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.savedMessagesForwarded); + } + + public void hideReactionsDialog() { + if (reactionsContainerLayout.getReactionsWindow() != null) { + reactionsContainerLayout.dismissWindow(); + if (reactionsContainerLayout.getReactionsWindow().containerView != null) { + reactionsContainerLayout.getReactionsWindow().containerView.animate().alpha(0).setDuration(180).start(); + } + } + } + + @Override + protected int getMeasuredBackgroundHeight() { + return textView.getMeasuredHeight() + AndroidUtilities.dp(30); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.savedMessagesForwarded) { + newMessagesByIds = (SparseLongArray) args[0]; + } + } + } + public static class LottieLayout extends ButtonLayout { public RLottieImageView imageView; - public LinkSpanDrawable.LinksTextView textView; + public TextView textView; private int textColor; @@ -1322,6 +1484,10 @@ public class Bulletin { addView(imageView, LayoutHelper.createFrameRelatively(56, 48, Gravity.START | Gravity.CENTER_VERTICAL)); textView = new LinkSpanDrawable.LinksTextView(context) { + { + setDisablePaddingsOffset(true); + } + @Override public void setText(CharSequence text, BufferType type) { text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), AndroidUtilities.dp(13), false); @@ -1329,7 +1495,6 @@ public class Bulletin { } }; NotificationCenter.listenEmojiLoading(textView); - textView.setDisablePaddingsOffset(true); textView.setSingleLine(); textView.setTypeface(Typeface.SANS_SERIF); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); @@ -1786,11 +1951,12 @@ public class Bulletin { } private final BulletinWindowLayout container; + private BulletinWindow(Context context, Delegate delegate) { super(context); setContentView( - container = new BulletinWindowLayout(context), - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + container = new BulletinWindowLayout(context), + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) ); if (Build.VERSION.SDK_INT >= 21) { container.setFitsSystemWindows(true); @@ -1804,7 +1970,7 @@ public class Bulletin { } }); if (Build.VERSION.SDK_INT >= 30) { - container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } else { container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java index d2fca34fd..8a91c6e50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -3,19 +3,22 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.text.Spannable; +import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextPaint; +import android.text.TextUtils; import android.text.style.ClickableSpan; -import android.util.Log; import android.util.TypedValue; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.ImageView; import androidx.annotation.CheckResult; import androidx.annotation.NonNull; @@ -40,6 +43,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.recorder.HintView2; @@ -1028,6 +1032,32 @@ public final class BulletinFactory { return Bulletin.make(containerLayout, layout, Bulletin.DURATION_SHORT); } + public boolean showForwardedBulletinWithTag(long did, int messagesCount) { + if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { + return false; + } + final Bulletin.LottieLayoutWithReactions layout = new Bulletin.LottieLayoutWithReactions(fragment, messagesCount); + CharSequence text; + if (did == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { + if (messagesCount <= 1) { + text = AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.FwdMessageToSavedMessages), -1, AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, SavedMessagesController::openSavedMessages); + } else { + text = AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.FwdMessagesToSavedMessages), -1, AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, SavedMessagesController::openSavedMessages); + } + } else { + return false; + } + layout.setAnimation(R.raw.saved_messages, 36, 36); + layout.textView.setText(text); + layout.textView.setSingleLine(false); + layout.textView.setMaxLines(2); + Bulletin bulletin = create(layout, 3500); + layout.setBulletin(bulletin); + bulletin.hideAfterBottomSheet(false); + bulletin.show(true); + return true; + } + @CheckResult public static Bulletin createForwardedBulletin(Context context, FrameLayout containerLayout, int dialogsCount, long did, int messagesCount, int backgroundColor, int textColor) { final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(context, null, backgroundColor, textColor); @@ -1182,6 +1212,39 @@ public final class BulletinFactory { layout.textView.setText(text); return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); } + + public Bulletin createMessagesTaggedBulletin(int messagesCount, TLRPC.Document document, Runnable onViewButton) { + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); + layout.setAnimation(R.raw.tag_icon_3, 36, 36); + layout.removeView(layout.textView); + layout.textView = new AnimatedEmojiSpan.TextViewEmojis(layout.getContext()); + layout.textView.setTypeface(Typeface.SANS_SERIF); + layout.textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + layout.textView.setEllipsize(TextUtils.TruncateAt.END); + layout.textView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); + + TextPaint textPaint = new TextPaint(); + textPaint.setTextSize(AndroidUtilities.dp(20)); + SpannableString spannable = new SpannableString("d"); + spannable.setSpan(new AnimatedEmojiSpan(document, textPaint.getFontMetricsInt()), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + layout.textView.setText( + new SpannableStringBuilder(messagesCount > 1 ? + LocaleController.formatPluralString("SavedTagMessagesTagged", messagesCount) : + LocaleController.getString(R.string.SavedTagMessageTagged)) + .append(" ") + .append(spannable) + ); + + if (onViewButton != null) { + layout.setButton(new Bulletin.UndoButton(getContext(), true, resourcesProvider).setText(LocaleController.getString(R.string.ViewAction)).setUndoAction(onViewButton)); + } + + layout.setTextColor(Theme.getColor(Theme.key_undo_infoColor, resourcesProvider)); + layout.addView(layout.textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 2, 8, 0)); + + return create(layout, Bulletin.DURATION_LONG); + } + //endregion public static class UndoObject { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 0080eeb3b..cbe99c606 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -1072,9 +1072,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return super.onSetAlpha(alpha); } + private VirtualViewHelper virtualViewHelper; + public ControlsView(Context context) { super(context); + virtualViewHelper = new VirtualViewHelper(this); + ViewCompat.setAccessibilityDelegate(this, virtualViewHelper); + periodDrawable = new CaptionContainerView.PeriodDrawable(); periodDrawable.setCallback(this); periodDrawable.setValue(1, voiceOnce, false); @@ -1498,6 +1503,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } + @Override + protected boolean dispatchHoverEvent(MotionEvent event) { + return super.dispatchHoverEvent(event) || virtualViewHelper.dispatchHoverEvent(event); + } + public void updateColors() { periodDrawable.updateColors( getThemedColor(Theme.key_chat_messagePanelVoiceLock), @@ -1580,6 +1590,53 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific protected boolean verifyDrawable(@NonNull Drawable who) { return who == periodDrawable || super.verifyDrawable(who); } + + + private class VirtualViewHelper extends ExploreByTouchHelper { + + public VirtualViewHelper(@NonNull View host) { + super(host); + } + + @Override + protected int getVirtualViewAt(float x, float y) { + if (sendButtonVisible && recordCircle != null && pauseRect.contains(x, y)) { + return 2; + } + if (onceVisible && (recordCircle != null && snapAnimationProgress > .1f) && onceRect.contains(x, y)) { + return 4; + } + return HOST_ID; + } + + @Override + protected void getVisibleVirtualViews(List list) { + if (sendButtonVisible) { + list.add(2); + } + if (onceVisible && (recordCircle != null && snapAnimationProgress > .1f)) { + list.add(4); + } + } + + @Override + protected void onPopulateNodeForVirtualView(int id, @NonNull AccessibilityNodeInfoCompat info) { + if (id == 2) { + rect.set((int) pauseRect.left, (int) pauseRect.top, (int) pauseRect.right, (int) pauseRect.bottom); + info.setBoundsInParent(rect); + info.setText(LocaleController.getString(transformToSeekbar > .5f ? R.string.AccActionResume : R.string.AccActionPause)); + } else if (id == 4) { + rect.set((int) onceRect.left, (int) onceRect.top, (int) onceRect.right, (int) onceRect.bottom); + info.setBoundsInParent(rect); + info.setText(LocaleController.getString(voiceOnce ? R.string.AccActionOnceDeactivate : R.string.AccActionOnceActivate)); + } + } + + @Override + protected boolean onPerformActionForVirtualView(int id, int action, @Nullable Bundle args) { + return true; + } + } } private float scale; @@ -2763,6 +2820,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48)); audioVideoButtonContainer.setFocusable(true); audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + // audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> { // createRecordCircle(); // if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { @@ -2932,9 +2990,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific // }); audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context); - audioVideoSendButton.setFocusable(true); - audioVideoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); - audioVideoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); + audioVideoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); +// audioVideoSendButton.setFocusable(true); +// audioVideoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); padding = dp(9.5f); audioVideoSendButton.setPadding(padding, padding, padding, padding); audioVideoSendButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); @@ -4165,7 +4223,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (sendWhenOnlineButton != null) { TLRPC.User user = parentFragment.getCurrentUser(); - if (user != null && !user.bot && !(user.status instanceof TLRPC.TL_userStatusEmpty) && !(user.status instanceof TLRPC.TL_userStatusOnline) && !(user.status instanceof TLRPC.TL_userStatusRecently)) { + if (user != null && !user.bot && !(user.status instanceof TLRPC.TL_userStatusEmpty) && !(user.status instanceof TLRPC.TL_userStatusOnline) && !(user.status instanceof TLRPC.TL_userStatusRecently) && !(user.status instanceof TLRPC.TL_userStatusLastMonth) && !(user.status instanceof TLRPC.TL_userStatusLastWeek)) { sendWhenOnlineButton.setVisibility(VISIBLE); } else { sendWhenOnlineButton.setVisibility(GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index 483a612c3..d9b6b1cf6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -298,7 +299,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } if (parentFragment != null && (parentFragment.getChatMode() == 0 || parentFragment.getChatMode() == ChatActivity.MODE_SAVED)) { - if ((!parentFragment.isThreadChat() || parentFragment.isTopic) && !UserObject.isReplyUser(parentFragment.getCurrentUser()) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { + if ((!parentFragment.isThreadChat() || parentFragment.isTopic) && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { setOnClickListener(v -> openProfile(false)); } @@ -315,6 +316,62 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } emojiStatusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(titleTextView, AndroidUtilities.dp(24)); + + setOnLongClickListener(v -> { + if (canSearch()) { + openSearch(); + return true; + } + return false; + }); + } + + private ButtonBounce bounce = new ButtonBounce(this); + private Runnable onLongClick = () -> { + pressed = false; + bounce.setPressed(false); + if (canSearch()) { + openSearch(); + } + }; + + private boolean pressed; + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && canSearch()) { + pressed = true; + bounce.setPressed(true); + AndroidUtilities.cancelRunOnUIThread(this.onLongClick); + AndroidUtilities.runOnUIThread(this.onLongClick, ViewConfiguration.getLongPressTimeout()); + return true; + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + if (pressed) { + bounce.setPressed(false); + pressed = false; + if (isClickable()) { + openProfile(false); + } + AndroidUtilities.cancelRunOnUIThread(this.onLongClick); + } + } + return super.onTouchEvent(ev); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.save(); + final float s = bounce.getScale(.02f); + canvas.scale(s, s, getWidth() / 2f, getHeight() / 2f); + super.dispatchDraw(canvas); + canvas.restore(); + } + + protected boolean canSearch() { + return false; + } + + protected void openSearch() { + } protected boolean onAvatarClick() { @@ -406,10 +463,10 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } public void openProfile(boolean byAvatar) { - openProfile(byAvatar, true); + openProfile(byAvatar, true, false); } - public void openProfile(boolean byAvatar, boolean fromChatAnimation) { + public void openProfile(boolean byAvatar, boolean fromChatAnimation, boolean removeLast) { if (byAvatar && (AndroidUtilities.isTablet() || AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y || !avatarImageView.getImageReceiver().hasNotThumb())) { byAvatar = false; } @@ -427,13 +484,17 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent if (user != null) { Bundle args = new Bundle(); - if (UserObject.isUserSelf(user) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { + if (UserObject.isUserSelf(user)) { + if (!sharedMediaPreloader.hasSharedMedia()) { + return; + } args.putLong("dialog_id", parentFragment.getDialogId()); - int[] media = new int[MediaDataController.MEDIA_TYPES_COUNT]; - System.arraycopy(sharedMediaPreloader.getLastMediaCount(), 0, media, 0, media.length); + if (parentFragment.getChatMode() == ChatActivity.MODE_SAVED) { + args.putLong("topic_id", parentFragment.getSavedDialogId()); + } MediaActivity fragment = new MediaActivity(args, sharedMediaPreloader); fragment.setChatInfo(parentFragment.getCurrentChatInfo()); - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } else { if (parentFragment.getChatMode() == ChatActivity.MODE_SAVED) { long dialogId = parentFragment.getSavedDialogId(); @@ -456,7 +517,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent if (fromChatAnimation) { fragment.setPlayProfileAnimation(byAvatar ? 2 : 1); } - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } } else if (chat != null) { Bundle args = new Bundle(); @@ -471,7 +532,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent if (fromChatAnimation) { fragment.setPlayProfileAnimation(byAvatar ? 2 : 1); } - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java index bbde88ed1..e0a9e0091 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -95,7 +95,7 @@ public class ChatGreetingsView extends LinearLayout { } } - private ImageView premiumIconView; + private RLottieImageView premiumIconView; private TextView premiumTextView; private TextView premiumButtonView; @@ -105,12 +105,17 @@ public class ChatGreetingsView extends LinearLayout { premiumLock = lock; if (premiumLock) { if (premiumIconView == null) { - premiumIconView = new ImageView(getContext()); + premiumIconView = new RLottieImageView(getContext()); premiumIconView.setScaleType(ImageView.ScaleType.CENTER); premiumIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); premiumIconView.setBackground(Theme.createCircleDrawable(dp(78), 0x1c000000)); - premiumIconView.setImageResource(R.drawable.large_message_lock); + premiumIconView.setAnimation(R.raw.large_message_lock, 80, 80); + premiumIconView.setOnClickListener(v -> { + premiumIconView.setProgress(0); + premiumIconView.playAnimation(); + }); } + premiumIconView.playAnimation(); if (premiumTextView == null) { premiumTextView = new TextView(getContext()); premiumTextView.setTextAlignment(TEXT_ALIGNMENT_CENTER); 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 b74e5a08b..cee8fe972 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java @@ -1,6 +1,9 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; +import android.util.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -25,6 +28,11 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { setOrientation(LinearLayout.VERTICAL); } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (maxHeight != 0) { @@ -46,20 +54,27 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { if (reactionsLayout.showCustomEmojiReaction()) { widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY); } + reactionsLayout.measureHint(); int reactionsLayoutTotalWidth = reactionsLayout.getTotalWidth(); View menuContainer = popupWindowLayout.getSwipeBack() != null ? popupWindowLayout.getSwipeBack().getChildAt(0) : popupWindowLayout.getChildAt(0); - int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16) + AndroidUtilities.dp(16) + AndroidUtilities.dp(36); - if (maxReactionsLayoutWidth > maxWidth) { + int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + dp(16) + dp(16) + dp(36); + int hintTextWidth = reactionsLayout.getHintTextWidth(); + if (hintTextWidth > maxReactionsLayoutWidth) { + maxReactionsLayoutWidth = hintTextWidth; + } else if (maxReactionsLayoutWidth > maxWidth) { maxReactionsLayoutWidth = maxWidth; } - reactionsLayout.bigCircleOffset = AndroidUtilities.dp(36); + reactionsLayout.bigCircleOffset = dp(36); if (reactionsLayout.showCustomEmojiReaction()) { reactionsLayout.getLayoutParams().width = reactionsLayoutTotalWidth; - reactionsLayout.bigCircleOffset = Math.max(reactionsLayoutTotalWidth - menuContainer.getMeasuredWidth() - AndroidUtilities.dp(36), AndroidUtilities.dp(36)); + reactionsLayout.bigCircleOffset = Math.max(reactionsLayoutTotalWidth - menuContainer.getMeasuredWidth() - dp(36), dp(36)); } else if (reactionsLayoutTotalWidth > maxReactionsLayoutWidth) { - int maxFullCount = ((maxReactionsLayoutWidth - AndroidUtilities.dp(16)) / AndroidUtilities.dp(36)) + 1; - int newWidth = maxFullCount * AndroidUtilities.dp(36) + AndroidUtilities.dp(16) - AndroidUtilities.dp(8); + int maxFullCount = ((maxReactionsLayoutWidth - dp(16)) / dp(36)) + 1; + int newWidth = maxFullCount * dp(36) + dp(8); + if (hintTextWidth + dp(24) > newWidth) { + newWidth = hintTextWidth + dp(24); + } if (newWidth > reactionsLayoutTotalWidth || maxFullCount == reactionsLayout.getItemsCount()) { newWidth = reactionsLayoutTotalWidth; } @@ -73,7 +88,7 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth(); } if (reactionsLayout.getLayoutParams().width != LayoutHelper.WRAP_CONTENT && reactionsLayout.getLayoutParams().width + widthDiff > maxWidth) { - widthDiff = maxWidth - reactionsLayout.getLayoutParams().width + AndroidUtilities.dp(8); + widthDiff = maxWidth - reactionsLayout.getLayoutParams().width + dp(8); } if (widthDiff < 0) { widthDiff = 0; @@ -84,23 +99,23 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { } else { popupLayoutLeftOffset = (maxWidth - menuContainer.getMeasuredWidth()) * 0.25f; reactionsLayout.bigCircleOffset -= popupLayoutLeftOffset; - if (reactionsLayout.bigCircleOffset < AndroidUtilities.dp(36)) { + if (reactionsLayout.bigCircleOffset < dp(36)) { popupLayoutLeftOffset = 0; - reactionsLayout.bigCircleOffset = AndroidUtilities.dp(36); + reactionsLayout.bigCircleOffset = dp(36); } updatePopupTranslation(); } if (bottomView != null) { if (reactionsLayout.showCustomEmojiReaction()) { - bottomView.getLayoutParams().width = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16); + bottomView.getLayoutParams().width = menuContainer.getMeasuredWidth() + dp(16); updatePopupTranslation(); } else { bottomView.getLayoutParams().width = LayoutHelper.MATCH_PARENT; } if (popupWindowLayout.getSwipeBack() != null) { - ((LayoutParams) bottomView.getLayoutParams()).rightMargin = widthDiff + AndroidUtilities.dp(36); + ((LayoutParams) bottomView.getLayoutParams()).rightMargin = widthDiff + dp(36); } else { - ((LayoutParams) bottomView.getLayoutParams()).rightMargin = AndroidUtilities.dp(36); + ((LayoutParams) bottomView.getLayoutParams()).rightMargin = dp(36); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java index 78b6c0176..98ef9a30f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java @@ -12,6 +12,7 @@ import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.view.animation.OvershootInterpolator; @@ -82,9 +83,11 @@ public class CounterView extends View { public boolean addServiceGradient; int currentCount; + CharSequence currentText; private boolean countAnimationIncrement; private ValueAnimator countAnimator; public float countChangeProgress = 1f; + private float countLayoutWidth; private StaticLayout countLayout; private StaticLayout countOldLayout; private StaticLayout countAnimationStableLayout; @@ -172,7 +175,15 @@ public class CounterView extends View { } public void setCount(int count, boolean animated) { - if (count == currentCount) { + setText(getStringOfCCount(count), animated, count, false); + } + + public void setText(CharSequence text, boolean animated) { + setText(text, animated, 1, true); + } + + public void setText(CharSequence text, boolean animated, int count, boolean isText) { + if (TextUtils.equals(text, currentText)) { return; } if (countAnimator != null) { @@ -186,21 +197,23 @@ public class CounterView extends View { } if (!animated) { currentCount = count; + currentText = text; if (count == 0) { if (updateVisibility && parent != null) { parent.setVisibility(View.GONE); } return; } - String newStr = getStringOfCCount(count); - countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr))); + CharSequence newStr = text; // getStringOfCCount(count); + countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr.toString()))); countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + countLayoutWidth = countLayout.getLineCount() >= 1 ? countLayout.getLineWidth(0) : 0; if (parent != null) { parent.invalidate(); } return; } - String newStr = getStringOfCCount(count); + CharSequence newStr = text; // getStringOfCCount(count); if (animated) { if (countAnimator != null) { @@ -244,9 +257,9 @@ public class CounterView extends View { countAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); } if (countLayout != null) { - String oldStr = getStringOfCCount(currentCount); + CharSequence oldStr = currentText; // getStringOfCCount(currentCount); - if (oldStr.length() == newStr.length()) { + if (oldStr.length() == newStr.length() && !isText) { SpannableStringBuilder oldSpannableStr = new SpannableStringBuilder(oldStr); SpannableStringBuilder newSpannableStr = new SpannableStringBuilder(newStr); SpannableStringBuilder stableStr = new SpannableStringBuilder(newStr); @@ -259,7 +272,7 @@ public class CounterView extends View { } } - int countOldWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(oldStr))); + int countOldWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(oldStr.toString()))); countOldLayout = new StaticLayout(oldSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); countAnimationStableLayout = new StaticLayout(stableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); countAnimationInLayout = new StaticLayout(newSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); @@ -272,16 +285,22 @@ public class CounterView extends View { countAnimator.start(); } if (count > 0) { - countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr))); + countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr.toString()))); countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + countLayoutWidth = countLayout.getLineCount() >= 1 ? countLayout.getLineWidth(0) : 0; } currentCount = count; + currentText = newStr; if (parent != null) { parent.invalidate(); } } + public int getCurrentWidth() { + return (int) Math.ceil(countLayoutWidth); + } + private String getStringOfCCount(int count) { if (shortFormat) { return AndroidUtilities.formatWholeNumber(count, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index 7b0cfd2f6..1b80517e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -651,6 +651,7 @@ public class EditTextBoldCursor extends EditTextEffects { } } hintLayout = new StaticLayout(text, paint, AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + invalidate(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java index 0dd4942ed..783ba4b1c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java @@ -269,35 +269,23 @@ public class EditTextCaption extends EditTextBoldCursor { AndroidUtilities.showKeyboard(editText); }); creationLinkDialog.showDelayed(250); - if (editText != null) { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); - if (layoutParams != null) { - if (layoutParams instanceof FrameLayout.LayoutParams) { - ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; - } - layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - editText.setLayoutParams(layoutParams); - } - editText.setSelection(0, editText.getText().length()); - } } else { builder.show().setOnShowListener(dialog -> { editText.requestFocus(); AndroidUtilities.showKeyboard(editText); }); - if (editText != null) { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); - if (layoutParams != null) { - if (layoutParams instanceof FrameLayout.LayoutParams) { - ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; - } - layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - editText.setLayoutParams(layoutParams); + } + if (editText != null) { + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); + if (layoutParams != null) { + if (layoutParams instanceof FrameLayout.LayoutParams) { + ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; } - editText.setSelection(0, editText.getText().length()); + layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.height = AndroidUtilities.dp(36); + editText.setLayoutParams(layoutParams); } + editText.setSelection(0, editText.getText().length()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java index 26c4620d7..cf43d6dad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -476,6 +476,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not editText.setSelection(selection); } + public void setSelection(int from, int to) { + editText.setSelection(from, to); + } + public void hidePopup(boolean byBackButton) { if (isPopupShowing()) { showPopup(0); @@ -521,6 +525,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } public void openKeyboard() { + editText.requestFocus(); AndroidUtilities.showKeyboard(editText); } 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 5fadf30bc..05169bdd7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -1648,7 +1648,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter break; case DO_SHUTDOWN_MESSAGE: finish(); - if (recording && inputMessage.arg2 != -2) { + if (recording && inputMessage.arg2 != -2 && videoEncoder != null) { videoEncoder.stopRecording(inputMessage.arg1, inputMessage.arg2); } Looper looper = Looper.myLooper(); 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 853df57b2..69b182e82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -80,6 +80,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha private TLRPC.ChatFull currentChatInfo; private TLRPC.UserFull currentUserInfo; private long dialogId; + private long topicId; private FrameLayout titlesContainer; private FrameLayout[] titles = new FrameLayout[2]; private SimpleTextView[] nameTextView = new SimpleTextView[2]; @@ -116,6 +117,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha public boolean onFragmentCreate() { type = getArguments().getInt("type", TYPE_MEDIA); dialogId = getArguments().getLong("dialog_id"); + topicId = getArguments().getLong("topic_id", 0); int defaultTab = SharedMediaLayout.TAB_PHOTOVIDEO; if (type == TYPE_ARCHIVED_CHANNEL_STORIES) { defaultTab = SharedMediaLayout.TAB_ARCHIVED_STORIES; @@ -126,7 +128,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); getNotificationCenter().addObserver(this, NotificationCenter.storiesEnabledUpdate); - if (DialogObject.isUserDialog(dialogId)) { + if (DialogObject.isUserDialog(dialogId) && topicId == 0) { TLRPC.User user = getMessagesController().getUser(dialogId); if (UserObject.isUserSelf(user)) { getMessagesController().loadUserInfo(user, false, this.classGuid); @@ -210,10 +212,12 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } } else if (id == 10) { sharedMediaLayout.showMediaCalendar(sharedMediaLayout.getClosestTab(), false); + } else if (id == 11) { + sharedMediaLayout.closeActionMode(true); + sharedMediaLayout.getSearchItem().openSearch(false); } } }); - actionBar.setColorFilterMode(PorterDuff.Mode.SRC_IN); FrameLayout avatarContainer = new FrameLayout(context); SizeNotifierFrameLayout fragmentView = new SizeNotifierFrameLayout(context) { @@ -386,7 +390,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } }; avatarImageView.getImageReceiver().setAllowDecodeSingleFrame(true); - avatarImageView.setRoundRadius(dp(21)); + avatarImageView.setRoundRadius(dp(getDialogId() == getUserConfig().getClientUserId() && topicId == 0 && getMessagesController().savedViewAsChats ? 13 : 21)); avatarImageView.setPivotX(0); avatarImageView.setPivotY(0); AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -537,7 +541,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha hideFloatingButton(true, false); } - if (type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 0) { + if (type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && topicId == 0 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().hasDialogs()) { initialTab = SharedMediaLayout.TAB_SAVED_DIALOGS; } sharedMediaLayout = new SharedMediaLayout(context, dialogId, sharedMediaPreloader, 0, null, currentChatInfo, currentUserInfo, initialTab, this, new SharedMediaLayout.Delegate() { @@ -616,7 +620,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha @Override protected boolean includeSavedDialogs() { - return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId(); + return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && topicId == 0; } @Override @@ -752,9 +756,15 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } } }; + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + } sharedMediaLayout.setPinnedToTop(true); sharedMediaLayout.getSearchItem().setTranslationY(0); sharedMediaLayout.photoVideoOptionsItem.setTranslationY(0); + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setTranslationY(0); + } if (type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES) { fragmentView.addView(sharedMediaLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 64)); @@ -779,14 +789,26 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha fragmentView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); } + long avatarDialogId = dialogId; + if (topicId != 0 && dialogId == getUserConfig().getClientUserId()) { + avatarDialogId = topicId; + } TLObject avatarObject = null; if (type == TYPE_ARCHIVED_CHANNEL_STORIES) { nameTextView[0].setText(LocaleController.getString("ProfileStoriesArchive")); } else if (type == TYPE_STORIES) { nameTextView[0].setText(LocaleController.getString("ProfileMyStories")); nameTextView[1].setText(LocaleController.getString("ProfileStoriesArchive")); - } else if (DialogObject.isEncryptedDialog(dialogId)) { - TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); + } else if (avatarDialogId == UserObject.ANONYMOUS) { + nameTextView[0].setText(LocaleController.getString(R.string.AnonymousForward)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_ANONYMOUS); + avatarDrawable.setScaleSize(.75f); + } else if (topicId != 0 && avatarDialogId == getUserConfig().getClientUserId()) { + nameTextView[0].setText(LocaleController.getString(R.string.MyNotes)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_MY_NOTES); + avatarDrawable.setScaleSize(.75f); + } else if (DialogObject.isEncryptedDialog(avatarDialogId)) { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(avatarDialogId)); if (encryptedChat != null) { TLRPC.User user = getMessagesController().getUser(encryptedChat.user_id); if (user != null) { @@ -795,8 +817,8 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha avatarObject = user; } } - } else if (DialogObject.isUserDialog(dialogId)) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + } else if (DialogObject.isUserDialog(avatarDialogId)) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(avatarDialogId); if (user != null) { if (user.self) { nameTextView[0].setText(LocaleController.getString("SavedMessages", R.string.SavedMessages)); @@ -809,7 +831,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } } } else { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-avatarDialogId); if (chat != null) { nameTextView[0].setText(chat.title); avatarDrawable.setInfo(currentAccount, chat); @@ -827,6 +849,13 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha if (sharedMediaLayout.isSearchItemVisible() && type != TYPE_STORIES) { sharedMediaLayout.getSearchItem().setVisibility(View.VISIBLE); } + if (sharedMediaLayout.searchItemIcon != null && initialTab != SharedMediaLayout.TAB_SAVED_DIALOGS) { + sharedMediaLayout.searchItemIcon.setVisibility(View.GONE); + } + if (sharedMediaLayout.getSearchOptionsItem() != null && type != TYPE_STORIES) { + sharedMediaLayout.animateSearchToOptions(!sharedMediaLayout.isSearchItemVisible(), false); + sharedMediaLayout.getSearchOptionsItem().setVisibility(View.VISIBLE); + } if (sharedMediaLayout.isCalendarItemVisible() && type != TYPE_STORIES) { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); } else { @@ -1114,8 +1143,12 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha private void updateColors() { + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + } actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setTitleColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); nameTextView[0].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -1160,11 +1193,9 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } private class StoriesTabsView extends BottomPagerTabs { - public StoriesTabsView(Context context, Theme.ResourcesProvider resourcesProvider) { super(context, resourcesProvider); } - @Override public Tab[] createTabs() { Tab[] tabs = new Tab[] { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java index a4c57f540..e334d49cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java @@ -693,7 +693,7 @@ public class MessagePreviewView extends FrameLayout { MessageObject message = messages.previewMessages.get(position); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { - MessageObject.GroupedMessagePosition pos = group.positions.get(message); + MessageObject.GroupedMessagePosition pos = group.getPosition(message); if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -733,7 +733,7 @@ public class MessagePreviewView extends FrameLayout { MessageObject message = messages.previewMessages.get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { - return groupedMessages.positions.get(message).spanSize; + return groupedMessages.getPosition(message).spanSize; } } return 1000; @@ -1691,7 +1691,7 @@ public class MessagePreviewView extends FrameLayout { MessageObject.GroupedMessages groupedMessages = null; if (message.getGroupId() != 0) { groupedMessages = messages.groupedMessagesMap.get(message.getGroupId()); - if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { + if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.getPosition(message) == null)) { groupedMessages = null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java index 6930c5103..f4cbdf7f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java @@ -43,6 +43,8 @@ import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.HintView2; +import java.util.Date; + public class MessagePrivateSeenView extends FrameLayout { private final int currentAccount; @@ -57,12 +59,15 @@ public class MessagePrivateSeenView extends FrameLayout { private final int messageId; private final Runnable dismiss; + private final int messageDiff; + public MessagePrivateSeenView(Context context, @NonNull MessageObject messageObject, Runnable dismiss, Theme.ResourcesProvider resourcesProvider) { super(context); currentAccount = messageObject.currentAccount; this.resourcesProvider = resourcesProvider; this.dismiss = dismiss; + messageDiff = ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date; dialogId = messageObject.getDialogId(); messageId = messageObject.getId(); @@ -126,7 +131,7 @@ public class MessagePrivateSeenView extends FrameLayout { } } else if (res instanceof TLRPC.TL_outboxReadDate) { TLRPC.TL_outboxReadDate r = (TLRPC.TL_outboxReadDate) res; - valueTextView.setText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatSeenDate(r.date))); + valueTextView.setText(LocaleController.formatPmSeenDate(r.date)); premiumTextView.setVisibility(View.GONE); } valueLayout.animate().alpha(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); @@ -302,22 +307,29 @@ public class MessagePrivateSeenView extends FrameLayout { if (minWidth < 0) { minWidth = 0; + final long date = System.currentTimeMillis(); minWidth = Math.max(minWidth, dp(40 + 96 + 8)); minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.getString(R.string.PmReadUnknown))); minWidth = Math.max(minWidth, dp(40 + 16 + 8) + valueTextView.getPaint().measureText(LocaleController.getString(R.string.PmRead) + premiumTextView.getPaint().measureText(LocaleController.getString(R.string.PmReadShowWhen)))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.TodayAtFormattedWithToday, "99:99")))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.YesterdayAtFormatted, "99:99")))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.formatDateAtTime, "99.99.99", "99:99")))); + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadTodayAt, LocaleController.getInstance().formatterDay.format(new Date(date))))); + if (messageDiff > 60 * 60 * 24) { + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadYesterdayAt, LocaleController.getInstance().formatterDay.format(new Date(date))))); + } + if (messageDiff > 60 * 60 * 24 * 2) { + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadDateTimeAt, LocaleController.getInstance().formatterDayMonth.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadDateTimeAt, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); + } } - if (width < minWidth) { - width = (int) minWidth; - } if (parent != null && parent.getWidth() > 0) { width = parent.getWidth(); widthMode = MeasureSpec.EXACTLY; } + if (width < minWidth || widthMode == MeasureSpec.AT_MOST) { + width = (int) minWidth; + widthMode = MeasureSpec.EXACTLY; + } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java index d17b18c29..269f9ff78 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java @@ -792,7 +792,7 @@ public class MessageEntityView extends EntityView { MessageObject message = messageObjects.get(position); boolean pinnedTop = false; if (groupedMessages != null) { - MessageObject.GroupedMessagePosition p = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition p = groupedMessages.getPosition(message); if (p != null) { pinnedTop = p.minY != 0; } @@ -825,7 +825,7 @@ public class MessageEntityView extends EntityView { position = messageObjects.size() - 1 - position; if (groupedMessages != null && position >= 0 && position < messageObjects.size()) { MessageObject message = messageObjects.get(position); - MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition pos = groupedMessages.getPosition(message); if (pos == null || pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -849,7 +849,7 @@ public class MessageEntityView extends EntityView { position = messageObjects.size() - 1 - position; if (groupedMessages != null && position >= 0 && position < groupedMessages.messages.size()) { MessageObject message = groupedMessages.messages.get(position); - MessageObject.GroupedMessagePosition groupedPosition = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition groupedPosition = groupedMessages.getPosition(message); if (groupedPosition != null) { return groupedPosition.spanSize; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java index 05072ce5b..b2c7ed183 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java @@ -648,6 +648,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView imp fireworksOverlay.start(); fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); headerView.boostCounterView.setCount(canApplyBoost.boostCount, true); + recyclerListView.smoothScrollToPosition(0); } private void sendInviteMessages() { @@ -1092,7 +1093,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView imp view.setPadding(0, 0, 0, AndroidUtilities.dp(8)); break; case VIEW_TYPE_USER: - view = new GroupCreateUserCell(context, 1, 8, false); + view = new GroupCreateUserCell(context, 1, 0, false); break; case VIEW_TYPE_PROGRESS: FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, null); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java index 3367a1760..5e5912aea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java @@ -488,8 +488,6 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumReactions)); premiumButtonView.setIcon(R.raw.unlock_icon); - } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || startType == PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED || startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || startType == PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT) { - premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.AboutTelegramPremium)); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumIcons)); premiumButtonView.setIcon(R.raw.unlock_icon); @@ -534,6 +532,7 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), true); actionBar.setCastShadows(true); actionBar.setExtraHeight(AndroidUtilities.dp(2)); @@ -677,8 +676,11 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati title.setText(LocaleController.getString("AdditionalReactions", R.string.AdditionalReactions)); description.setText(AndroidUtilities.replaceTags(LocaleController.getString("AdditionalReactionsDescription", R.string.AdditionalReactionsDescription))); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { - title.setText(LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds)); - description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewNoAdsDescription2", R.string.PremiumPreviewNoAdsDescription2))); + title.setText(LocaleController.getString(R.string.PremiumPreviewNoAds)); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewNoAdsDescription2))); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { + title.setText(LocaleController.getString(R.string.PremiumPreviewTags)); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewTagsDescription))); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { title.setText(LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon)); description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewAppIconDescription2", R.string.PremiumPreviewAppIconDescription2))); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java index 90f593b08..290bddd2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -17,6 +17,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.voip.CellFlickerDrawable; public class PremiumLockIconView extends ImageView { @@ -61,6 +62,7 @@ public class PremiumLockIconView extends ImageView { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Paint oldShaderPaint; ImageReceiver imageReceiver; + AnimatedEmojiDrawable emojiDrawable; float shaderCrossfadeProgress = 1f; boolean waitingImage; boolean wasDrawn; @@ -106,6 +108,14 @@ public class PremiumLockIconView extends ImageView { if (imageReceiver != null && imageReceiver.getBitmap() != null) { waitingImage = false; setColor(AndroidUtilities.getDominantColor(imageReceiver.getBitmap())); + } else if (emojiDrawable != null) { + int color = AnimatedEmojiDrawable.getDominantColor(emojiDrawable); + if (color != 0) { + waitingImage = false; + setColor(color); + } else { + invalidate(); + } } else { invalidate(); } @@ -163,6 +173,14 @@ public class PremiumLockIconView extends ImageView { } } + public void setAnimatedEmojiDrawable(AnimatedEmojiDrawable emojiDrawable) { + this.emojiDrawable = emojiDrawable; + if (emojiDrawable != null) { + waitingImage = true; + invalidate(); + } + } + public ImageReceiver getImageReceiver() { return imageReceiver; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java index 05c536b51..9e02c3037 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java @@ -267,6 +267,18 @@ public class StarParticlesView extends View { stars[i] = SvgHelper.getBitmap(R.raw.premium_object_star2, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 30)); svg = true; continue; + } else if (type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { + int res; + if (i == 0) { + res = R.raw.premium_object_tag; + } else if (i == 1) { + res = R.raw.premium_object_check; + } else { + res = R.raw.premium_object_star; + } + stars[i] = SvgHelper.getBitmap(res, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 30)); + svg = true; + continue; } bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); @@ -540,6 +552,7 @@ public class StarParticlesView extends View { type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || type == PremiumPreviewFragment.PREMIUM_FEATURE_WALLPAPER || type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java index c055a6b23..58e57d3c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java @@ -61,6 +61,11 @@ public class StoriesPageView extends BaseListPageView { LocaleController.getString("PremiumStoriesStealthDescription", R.string.PremiumStoriesStealthDescription), PremiumPreviewFragment.PREMIUM_FEATURE_STORIES_STEALTH_MODE )); + itemsTmp.add(new Item(VIEW_TYPE_ITEM, R.drawable.menu_quality_hd, + LocaleController.getString(R.string.PremiumStoriesQuality), + LocaleController.getString(R.string.PremiumStoriesQualityDescription), + PremiumPreviewFragment.PREMIUM_FEATURE_STORIES_QUALITY + )); itemsTmp.add(new Item(VIEW_TYPE_ITEM, R.drawable.msg_stories_views, LocaleController.getString("PremiumStoriesViews", R.string.PremiumStoriesViews), LocaleController.getString("PremiumStoriesViewsDescription", R.string.PremiumStoriesViewsDescription), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java index a514de455..c138f73ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java @@ -131,12 +131,14 @@ public class VideoScreenPreview extends FrameLayout implements PagerHeaderView, type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || - type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { + type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS + ) { starDrawable = new StarParticlesView.Drawable(40); starDrawable.speedScale = 3; starDrawable.type = type; - if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { starDrawable.size1 = 14; starDrawable.size2 = 18; starDrawable.size3 = 18; @@ -325,6 +327,7 @@ public class VideoScreenPreview extends FrameLayout implements PagerHeaderView, type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { starDrawable.rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java index 6ecddba60..39b2edd82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java @@ -444,8 +444,13 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp actionButton.setShowZero(false); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); if (selectedIds.size() == 0) { - stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + if (LocaleController.isRTL) { + stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, stringBuilder.length() - 1, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + } } else { stringBuilder.append(LocaleController.getString("GiftPremiumProceedBtn", R.string.GiftPremiumProceedBtn)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java index 739b4193e..3fc8967c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java @@ -11,6 +11,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Build; import android.text.Editable; import android.text.Layout; import android.text.SpannableString; @@ -706,7 +707,12 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not private boolean closeKeyboard() { if (emojiKeyboardVisible) { emojiKeyboardVisible = false; - editText.clearFocus(); + if (isClearFocusNotWorking()) { + switchLayout.setFocusableInTouchMode(true); + switchLayout.requestFocus(); + } else { + editText.clearFocus(); + } updateScrollViewMarginBottom(0); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); bottomDialogLayout.animate().setListener(null).cancel(); @@ -717,6 +723,9 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not public void onAnimationEnd(Animator animation) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); bottomDialogLayout.setVisibility(View.INVISIBLE); + if (isClearFocusNotWorking()) { + switchLayout.setFocusableInTouchMode(false); + } } }).start(); return true; @@ -724,6 +733,10 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not return false; } + private boolean isClearFocusNotWorking() { + return Build.MODEL.toLowerCase().startsWith("zte") && Build.VERSION.SDK_INT <= Build.VERSION_CODES.P; + } + private void updateScrollViewMarginBottom(int margin) { ViewGroup.MarginLayoutParams marginLayoutParams = ((ViewGroup.MarginLayoutParams) scrollView.getLayoutParams()); marginLayoutParams.bottomMargin = margin; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java index e30d22e70..7cca87513 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java @@ -66,7 +66,9 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout { private void checkCreateReactionsLayout() { if (reactionsContainerLayout == null) { - reactionsContainerLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_DEFAULT, parentFragment, getContext(), parentFragment.getCurrentAccount(), parentFragment.getResourceProvider()) { + final boolean tags = parentFragment.getUserConfig().getClientUserId() == parentFragment.getDialogId(); + + reactionsContainerLayout = new ReactionsContainerLayout(tags ? ReactionsContainerLayout.TYPE_TAGS : ReactionsContainerLayout.TYPE_DEFAULT, parentFragment, getContext(), parentFragment.getCurrentAccount(), parentFragment.getResourceProvider()) { float enabledAlpha = 1f; long lastUpdate; @@ -110,7 +112,7 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout { reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { - parentFragment.selectReaction(currentPrimaryObject, reactionsContainerLayout, view, 0, 0, visibleReaction, false, longpress, addToRecent); + parentFragment.selectReaction(currentPrimaryObject, reactionsContainerLayout, view, 0, 0, visibleReaction, false, longpress, addToRecent, false); AndroidUtilities.runOnUIThread(() -> { if (reactionsContainerLayout != null) { reactionsContainerLayout.dismissParent(true); 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 78cbb7cb3..d2ed41a28 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 @@ -2,6 +2,7 @@ package org.telegram.ui.Components.Reactions; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY_LIKES; +import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_TAGS; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -66,7 +67,7 @@ import java.util.List; public class CustomEmojiReactionsWindow { - ContainerView containerView; + public ContainerView containerView; WindowManager windowManager; public FrameLayout windowView; boolean attachToParent; @@ -164,7 +165,7 @@ public class CustomEmojiReactionsWindow { // sizeNotifierFrameLayout.setFitsSystemWindows(true); containerView = new ContainerView(context); - int dialogType = reactionsContainerLayout.showExpandableReactions() ? SelectAnimatedEmojiDialog.TYPE_EXPANDABLE_REACTIONS : SelectAnimatedEmojiDialog.TYPE_REACTIONS; + final int dialogType = reactionsContainerLayout.getWindowType(); selectAnimatedEmojiDialog = new SelectAnimatedEmojiDialog(baseFragment, context, false, null, dialogType, type != TYPE_STORY, resourcesProvider, 16) { @Override @@ -309,7 +310,7 @@ public class CustomEmojiReactionsWindow { private WindowManager.LayoutParams createLayoutParams(boolean focusable) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.width = lp.height = WindowManager.LayoutParams.MATCH_PARENT; - lp.type = type == ReactionsContainerLayout.TYPE_DEFAULT ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL : WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + lp.type = (type == ReactionsContainerLayout.TYPE_DEFAULT || type == ReactionsContainerLayout.TYPE_TAGS) ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL : WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; if (focusable) { lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; @@ -699,7 +700,7 @@ public class CustomEmojiReactionsWindow { } } - private class ContainerView extends FrameLayout { + public class ContainerView extends FrameLayout { Drawable shadow; Rect shadowPad = new Rect(); @@ -781,7 +782,7 @@ public class CustomEmojiReactionsWindow { } if (reactionsContainerLayout.hintView != null) { canvas.save(); - canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.hintView.getY()); + canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.hintView.getY() - (type == TYPE_TAGS ? reactionsContainerLayout.rect.top : 0)); canvas.saveLayerAlpha( 0, 0, reactionsContainerLayout.hintView.getMeasuredWidth(), reactionsContainerLayout.hintView.getMeasuredHeight(), (int) (255 * reactionsContainerLayout.hintView.getAlpha() * (1f - enterTransitionProgress)), Canvas.ALL_SAVE_FLAG); reactionsContainerLayout.hintView.draw(canvas); canvas.restore(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java index 3c6bfd6ee..caa5e0c36 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java @@ -12,6 +12,9 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextPaint; import android.text.TextUtils; import android.view.Gravity; @@ -19,14 +22,18 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.ChatListItemAnimator; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; @@ -38,8 +45,13 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AnimatedFileDrawable; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AvatarsDrawable; import org.telegram.ui.Components.CounterView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.RLottieDrawable; import java.util.ArrayList; import java.util.Collections; @@ -58,6 +70,14 @@ public class ReactionsLayoutInBubble { private static Paint tagPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private static Paint cutTagPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private static TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + public static void initPaints(Theme.ResourcesProvider resourcesProvider) { + paint.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider)); + textPaint.setColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); + textPaint.setTextSize(dp(12)); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + cutTagPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } public boolean isSmall; public int x; @@ -79,14 +99,14 @@ public class ReactionsLayoutInBubble { public boolean isEmpty; private float touchSlop; public int lastLineX; - ArrayList reactionButtons = new ArrayList<>(); + public ArrayList reactionButtons = new ArrayList<>(); ArrayList outButtons = new ArrayList<>(); HashMap lastDrawingReactionButtons = new HashMap<>(); HashMap lastDrawingReactionButtonsTmp = new HashMap<>(); ChatMessageCell parentView; MessageObject messageObject; Theme.ResourcesProvider resourcesProvider; - private String scrimViewReaction; + private Integer scrimViewReaction; int availableWidth; private int lastDrawnWidth; @@ -117,12 +137,8 @@ public class ReactionsLayoutInBubble { public ReactionsLayoutInBubble(ChatMessageCell parentView) { this.parentView = parentView; currentAccount = UserConfig.selectedAccount; - paint.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider)); - textPaint.setColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); - textPaint.setTextSize(dp(12)); - textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + initPaints(resourcesProvider); touchSlop = ViewConfiguration.get(ApplicationLoader.applicationContext).getScaledTouchSlop(); - cutTagPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } public static boolean equalsTLReaction(TLRPC.Reaction reaction, TLRPC.Reaction reaction1) { @@ -135,9 +151,10 @@ public class ReactionsLayoutInBubble { return false; } - public void setMessage(MessageObject messageObject, boolean isSmall, Theme.ResourcesProvider resourcesProvider) { + public void setMessage(MessageObject messageObject, boolean isSmall, boolean isTag, Theme.ResourcesProvider resourcesProvider) { this.resourcesProvider = resourcesProvider; this.isSmall = isSmall; + this.tags = isTag; this.messageObject = messageObject; ArrayList oldButtons = new ArrayList<>(reactionButtons); hasUnreadReactions = false; @@ -159,9 +176,9 @@ public class ReactionsLayoutInBubble { // break; // } // } - ReactionButton button = new ReactionLayoutButton(old, reactionCount, isSmall); + ReactionButton button = new ReactionLayoutButton(old, reactionCount, isSmall, isTag); reactionButtons.add(button); - if (!isSmall && messageObject.messageOwner.reactions.recent_reactions != null) { + if (!isSmall && !isTag && messageObject.messageOwner.reactions.recent_reactions != null) { ArrayList users = null; if (messageObject.getDialogId() > 0 && !UserObject.isReplyUser(messageObject.getDialogId())) { @@ -212,7 +229,7 @@ public class ReactionsLayoutInBubble { } } if (isSmall && reactionCount.count > 1 && reactionCount.chosen) { - ReactionButton button2 = new ReactionLayoutButton(null, reactionCount, isSmall); + ReactionButton button2 = new ReactionLayoutButton(null, reactionCount, isSmall, isTag); reactionButtons.add(button2); reactionButtons.get(0).isSelected = false; reactionButtons.get(1).isSelected = true; @@ -261,6 +278,14 @@ public class ReactionsLayoutInBubble { if (button.isSmall) { button.width = dp(14); button.height = dp(14); + } else if (button.isTag) { + button.width = dp(42); + button.height = dp(26); + if (button.hasName) { + button.width += button.textDrawable.getAnimateToWidth() + dp(8); + } else if (button.counterDrawable != null && button.count > 1) { + button.width += button.counterDrawable.getCurrentWidth() + dp(8); + } } else { button.width = (int) (dp(8) + dp(20) + dp(4)); if (button.avatarsDrawable != null && button.users.size() > 0) { @@ -269,8 +294,10 @@ public class ReactionsLayoutInBubble { int c2 = button.users.size() > 1 ? button.users.size() - 1 : 0; button.width += dp(2) + c1 * dp(20) + c2 * dp(20) * 0.8f + dp(1); button.avatarsDrawable.height = dp(26); + } else if (button.hasName) { + button.width += button.textDrawable.getAnimateToWidth() + dp(8); } else { - button.width += button.counterDrawable.textPaint.measureText(button.countText) + dp(8); + button.width += button.counterDrawable.getCurrentWidth() + dp(8); } button.height = dp(26); } @@ -314,7 +341,7 @@ public class ReactionsLayoutInBubble { drawServiceShaderBackground = 0f; } - public void draw(Canvas canvas, float animationProgress, String drawOnlyReaction) { + public void draw(Canvas canvas, float animationProgress, Integer drawOnlyReaction) { if (isEmpty && outButtons.isEmpty()) { return; } @@ -329,7 +356,7 @@ public class ReactionsLayoutInBubble { } for (int i = 0; i < reactionButtons.size(); i++) { ReactionButton reactionButton = reactionButtons.get(i); - if (reactionButton.reaction.equals(scrimViewReaction) || (drawOnlyReaction != null && !reactionButton.reaction.equals(drawOnlyReaction))) { + if ((Objects.equals(reactionButton.reaction.hashCode(), scrimViewReaction)) || (drawOnlyReaction != null && reactionButton.reaction.hashCode() != drawOnlyReaction)) { continue; } canvas.save(); @@ -397,6 +424,7 @@ public class ReactionsLayoutInBubble { button.fromTextColor = lastButton.lastDrawnTextColor; button.fromBackgroundColor = lastButton.lastDrawnBackgroundColor; + button.fromTagDotColor = lastButton.lastDrawnTagDotColor; button.animationType = ANIMATION_TYPE_MOVE; if (button.count != lastButton.count && button.counterDrawable != null) { @@ -492,13 +520,13 @@ public class ReactionsLayoutInBubble { return lastDrawingReactionButtons.get(hash); } - public void setScrimReaction(String scrimViewReaction) { + public void setScrimReaction(Integer scrimViewReaction) { this.scrimViewReaction = scrimViewReaction; } public class ReactionLayoutButton extends ReactionButton { - public ReactionLayoutButton(ReactionButton reuseFrom, TLRPC.ReactionCount reactionCount, boolean isSmall) { - super(reuseFrom, currentAccount, parentView, reactionCount, isSmall, resourcesProvider); + public ReactionLayoutButton(ReactionButton reuseFrom, TLRPC.ReactionCount reactionCount, boolean isSmall, boolean isTag) { + super(reuseFrom, currentAccount, parentView, reactionCount, isSmall, isTag, resourcesProvider); } @Override @@ -532,6 +560,13 @@ public class ReactionsLayoutInBubble { } } + public boolean verifyDrawable(Drawable drawable) { + if (drawable instanceof AnimatedTextView.AnimatedTextDrawable) { + return true; + } + return false; + } + public static class ReactionButton { private final TLRPC.ReactionCount reactionCount; @@ -541,6 +576,7 @@ public class ReactionsLayoutInBubble { public int animateFromY; public int animateFromWidth; public int fromBackgroundColor; + public int fromTagDotColor; public int fromTextColor; public int realCount; public int choosenOrder; @@ -555,15 +591,19 @@ public class ReactionsLayoutInBubble { VisibleReaction visibleReaction; android.graphics.Rect drawingImageRect = new Rect(); + public boolean hasName; + public String name; + public int count; public int x; public int y; public int width; public int height; - ImageReceiver imageReceiver; - AnimatedEmojiDrawable animatedEmojiDrawable; + public ImageReceiver imageReceiver; + public AnimatedEmojiDrawable animatedEmojiDrawable; int animatedEmojiDrawableColor; public CounterView.CounterDrawable counterDrawable; + public AnimatedTextView.AnimatedTextDrawable textDrawable; int backgroundColor; int textColor; int serviceBackgroundColor; @@ -571,8 +611,10 @@ public class ReactionsLayoutInBubble { public int lastDrawnTextColor; public int lastDrawnBackgroundColor; + public int lastDrawnTagDotColor; boolean isSelected; + public boolean isTag; AvatarsDrawable avatarsDrawable; ArrayList users; @@ -581,13 +623,17 @@ public class ReactionsLayoutInBubble { private final Theme.ResourcesProvider resourcesProvider; protected int getCacheType() { + if (isTag) { + return AnimatedEmojiDrawable.CACHE_TYPE_SAVED_REACTION; + } return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; } - public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentView, TLRPC.ReactionCount reactionCount, boolean isSmall, Theme.ResourcesProvider resourcesProvider) { + public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentView, TLRPC.ReactionCount reactionCount, boolean isSmall, boolean isTag, Theme.ResourcesProvider resourcesProvider) { this.currentAccount = currentAccount; this.parentView = parentView; this.resourcesProvider = resourcesProvider; + this.isTag = isTag; if (reuseFrom != null) { counterDrawable = reuseFrom.counterDrawable; } @@ -597,6 +643,14 @@ public class ReactionsLayoutInBubble { if (counterDrawable == null) { counterDrawable = new CounterView.CounterDrawable(parentView, false, null); } + if (textDrawable == null) { + textDrawable = new AnimatedTextView.AnimatedTextDrawable(true, true, true); + textDrawable.setAnimationProperties(.4f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + textDrawable.setTextSize(dp(13)); + textDrawable.setCallback(parentView); + textDrawable.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); + } this.reactionCount = reactionCount; this.reaction = reactionCount.reaction; this.visibleReaction = VisibleReaction.fromTLReaction(reactionCount.reaction); @@ -612,7 +666,6 @@ public class ReactionsLayoutInBubble { } else { throw new RuntimeException("unsupported"); } - countText = Integer.toString(reactionCount.count); imageReceiver.setParentView(parentView); isSelected = reactionCount.chosen; counterDrawable.updateVisibility = false; @@ -633,17 +686,54 @@ public class ReactionsLayoutInBubble { counterDrawable.setSize(dp(26), dp(100)); counterDrawable.textPaint = textPaint; - counterDrawable.setCount(count, false); + if (isTag) { + name = MessagesController.getInstance(currentAccount).getSavedTagName(reaction); + hasName = !TextUtils.isEmpty(name); + } + if (hasName) { + textDrawable.setText(Emoji.replaceEmoji(name, textDrawable.getPaint().getFontMetricsInt(), false), !LocaleController.isRTL); + if (drawTextWithCounter()) { + countText = Integer.toString(reactionCount.count); + counterDrawable.setCount(count, false); + } else { + countText = ""; + counterDrawable.setCount(0, false); + } + } else { + if (textDrawable != null) { + textDrawable.setText("", false); + } + countText = Integer.toString(reactionCount.count); + counterDrawable.setCount(count, false); + } counterDrawable.setType(CounterView.CounterDrawable.TYPE_CHAT_REACTIONS); counterDrawable.gravity = Gravity.LEFT; } + private RectF bounds = new RectF(), rect2 = new RectF(); + private final Path tagPath = new Path(); + private void drawRoundRect(Canvas canvas, RectF rectF, float r, Paint paint) { + if (isTag) { + if (bounds.left != rectF.left || bounds.top != rectF.top || bounds.right != rectF.right || bounds.bottom != rectF.bottom) { + bounds.set(rectF); + fillTagPath(bounds, rect2, tagPath); + } + canvas.drawPath(tagPath, paint); + } else { + canvas.drawRoundRect(rectF, r, r, paint); + } + } + protected boolean isOutOwner() { return false; } protected boolean drawCounter() { - return count != 0 || counterDrawable.countChangeProgress != 1f; + return count != 0 && (!isTag || hasName || count != 1) || counterDrawable.countChangeProgress != 1f; + } + + protected boolean drawTextWithCounter() { + return false; } public void draw(Canvas canvas, float x, float y, float progress, float alpha, boolean drawOverlayScrim) { @@ -672,7 +762,11 @@ public class ReactionsLayoutInBubble { } updateColors(progress); textPaint.setColor(lastDrawnTextColor); + if (textDrawable != null) { + textDrawable.setTextColor(lastDrawnTextColor); + } paint.setColor(lastDrawnBackgroundColor); + final boolean cutTagCircle = isTag && drawTagDot() && Color.alpha(lastDrawnTagDotColor) == 0; if (alpha != 1f) { textPaint.setAlpha((int) (textPaint.getAlpha() * alpha)); @@ -695,20 +789,39 @@ public class ReactionsLayoutInBubble { int oldAlpha2 = paint2.getAlpha(); paint1.setAlpha((int) (oldAlpha * alpha * getDrawServiceShaderBackground())); paint2.setAlpha((int) (oldAlpha2 * alpha * getDrawServiceShaderBackground())); - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint1); + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint1); if (resourcesProvider != null ? resourcesProvider.hasGradientService() : Theme.hasGradientService()) { - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint2); + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint2); } paint1.setAlpha(oldAlpha); paint2.setAlpha(oldAlpha2); } if (drawOverlayScrim && getDrawServiceShaderBackground() < 1 && parentView instanceof ChatMessageCell) { Theme.MessageDrawable messageBackground = ((ChatMessageCell) parentView).getCurrentBackgroundDrawable(false); - if (messageBackground != null) { + if (messageBackground != null && !isTag) { canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, messageBackground.getPaint()); } } - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint); + if (cutTagCircle) { + AndroidUtilities.rectTmp.right += dp(4); + canvas.saveLayerAlpha(AndroidUtilities.rectTmp, 0xFF, Canvas.ALL_SAVE_FLAG); + AndroidUtilities.rectTmp.right -= dp(4); + } + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint); + if (isTag && drawTagDot()) { + Paint paint; + if (cutTagCircle) { + paint = cutTagPaint; + } else { + tagPaint.setColor(lastDrawnTagDotColor); + tagPaint.setAlpha((int) (tagPaint.getAlpha() * alpha)); + paint = tagPaint; + } + canvas.drawCircle(AndroidUtilities.rectTmp.right - dp(8.4f), AndroidUtilities.rectTmp.centerY(), dp(2.66f), paint); + } + if (cutTagCircle) { + canvas.restore(); + } if (imageReceiver != null) { int size, X; @@ -722,31 +835,47 @@ public class ReactionsLayoutInBubble { imageReceiver.setRoundRadius(0); } int Y = (int) ((height - size) / 2f); + if (isTag) { + X -= dp(2); + } drawingImageRect.set((int) x + X, (int) y + Y, (int) x + X + size, (int) y + Y + size); imageReceiver.setImageCoords(drawingImageRect); drawImage(canvas, alpha); } + float tx = 0; + if (textDrawable != null && textDrawable.isNotEmpty() > 0) { + canvas.save(); + canvas.translate(x + dp(hasName && !drawTagDot() ? 10 : (hasName ? 9 : 8)) + dp(20) + dp(2), y); + textDrawable.setBounds(0, 0, width, height); + textDrawable.draw(canvas); + textDrawable.setAlpha((int) (0xFF * alpha)); + canvas.restore(); + tx = textDrawable.getCurrentWidth() + dp(4) * textDrawable.isNotEmpty(); + } if (counterDrawable != null && drawCounter()) { canvas.save(); - canvas.translate(x + dp(8) + dp(20) + dp(2), y); + canvas.translate(x + dp(hasName && !drawTagDot() ? 10 : (hasName ? 9 : 8)) + dp(20) + dp(2) + tx, y); counterDrawable.draw(canvas); canvas.restore(); } - if (avatarsDrawable != null) { - canvas.save(); - canvas.translate(x + dp(10) + dp(20) + dp(2), y); - avatarsDrawable.setAlpha(alpha); - avatarsDrawable.setTransitionProgress(progress); - avatarsDrawable.onDraw(canvas); - canvas.restore(); + if (!isTag) { + if (avatarsDrawable != null) { + canvas.save(); + canvas.translate(x + dp(10) + dp(20) + dp(2), y); + avatarsDrawable.setAlpha(alpha); + avatarsDrawable.setTransitionProgress(progress); + avatarsDrawable.onDraw(canvas); + canvas.restore(); + } } } protected void updateColors(float progress) { lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, ColorUtils.blendARGB(textColor, serviceTextColor, getDrawServiceShaderBackground()), progress); lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, ColorUtils.blendARGB(backgroundColor, serviceBackgroundColor, getDrawServiceShaderBackground()), progress); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, AndroidUtilities.computePerceivedBrightness(lastDrawnBackgroundColor) > .8f ? 0 : 0x5affffff, progress); } protected boolean isPlaying() { @@ -870,6 +999,26 @@ public class ReactionsLayoutInBubble { animatedEmojiDrawable.removeView(parentView); } } + + public void startAnimation() { + ImageReceiver imageReceiver; + if (animatedEmojiDrawable != null && animatedEmojiDrawable.getImageReceiver() != null) { + imageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + imageReceiver = this.imageReceiver; + } + if (imageReceiver != null) { + RLottieDrawable rLottieDrawable = imageReceiver.getLottieAnimation(); + if (rLottieDrawable != null) { + rLottieDrawable.restart(true); + } else { + AnimatedFileDrawable animatedFileDrawable = imageReceiver.getAnimation(); + if (animatedFileDrawable != null) { + animatedFileDrawable.start(); + } + } + } + } } float lastX; @@ -1017,6 +1166,13 @@ public class ReactionsLayoutInBubble { imageReceiver.setAutoRepeat(0); imageReceiver.onAttachedToWindow(); animatedReactions.put(reaction, imageReceiver); + } else if (tags && reaction.documentId != 0) { + for (int i = 0; i < reactionButtons.size(); ++i) { + if (reaction.isSame(reactionButtons.get(i).reaction)) { + reactionButtons.get(i).startAnimation(); + return; + } + } } } @@ -1107,5 +1263,102 @@ public class ReactionsLayoutInBubble { } return false; } + + @NonNull + @Override + public String toString() { + if (!TextUtils.isEmpty(emojicon)) + return emojicon; + if (documentId != 0) { + TLRPC.Document document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, documentId); + if (document != null) { + return MessageObject.findAnimatedEmojiEmoticon(document, null); + } + } + return "VisibleReaction{" + documentId + ", " + emojicon + "}"; + } + + public CharSequence toCharSequence(Paint.FontMetricsInt fontMetrics, int cacheType) { + if (!TextUtils.isEmpty(emojicon)) { + return emojicon; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, fontMetrics); + emojiSpan.cacheType = cacheType; + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + + public CharSequence toCharSequence(Paint.FontMetricsInt fontMetrics) { + if (!TextUtils.isEmpty(emojicon)) { + return emojicon; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, fontMetrics); + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + + public CharSequence toCharSequence(int textSizeDp) { + TextPaint textPaint = new TextPaint(); + textPaint.setTextSize(AndroidUtilities.dp(textSizeDp)); + if (!TextUtils.isEmpty(emojicon)) { + CharSequence string = emojicon; + string = Emoji.replaceEmoji(string, textPaint.getFontMetricsInt(), false); + return string; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, textPaint.getFontMetricsInt()); + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + } + + public static boolean reactionsEqual(TLRPC.Reaction a, TLRPC.Reaction b) { + if (a instanceof TLRPC.TL_reactionEmoji) { + if (!(b instanceof TLRPC.TL_reactionEmoji)) + return false; + return TextUtils.equals(((TLRPC.TL_reactionEmoji) a).emoticon, ((TLRPC.TL_reactionEmoji) b).emoticon); + } else if (a instanceof TLRPC.TL_reactionCustomEmoji) { + if (!(b instanceof TLRPC.TL_reactionCustomEmoji)) + return false; + return ((TLRPC.TL_reactionCustomEmoji) a).document_id == ((TLRPC.TL_reactionCustomEmoji) b).document_id; + } + return false; + } + + public static void fillTagPath(RectF bounds, Path path) { + fillTagPath(bounds, AndroidUtilities.rectTmp, path); + } + public static void fillTagPath(RectF bounds, RectF tempRect, Path path) { + path.rewind(); + tempRect.set(bounds.left, bounds.top, bounds.left + dp(12), bounds.top + dp(12)); + path.arcTo(tempRect, -90, -90, false); + tempRect.set(bounds.left, bounds.bottom - dp(12), bounds.left + dp(12), bounds.bottom); + path.arcTo(tempRect, -180, -90, false); + + float arrowRound = bounds.height() > dp(26) ? 1.4f : 0f; + float x = bounds.right - dpf2(9.09f); + float x1 = x - dpf2(0.056f); + float x1a = x + dpf2(1.22f); + float x2 = x + dpf2(3.07f); + float x2a = x + dpf2(2.406f); + float x3 = x + dpf2(8.27f + arrowRound); + float x3a = x + dpf2(8.923f + arrowRound); + float ty2 = bounds.top + dpf2(1.753f); + float by2 = bounds.bottom - dpf2(1.753f); + float ty2a = bounds.top + dpf2(0.663f); + float by2a = bounds.bottom - dpf2(0.663f); + float ty3 = bounds.top + dpf2(10.263f + arrowRound); + float by3 = bounds.bottom - dpf2(10.263f + arrowRound); + float ty3a = bounds.top + dpf2(11.333f + arrowRound); + float by3a = bounds.bottom - dpf2(11.333f + arrowRound); + path.lineTo(x1, bounds.bottom); + path.cubicTo(x1a, bounds.bottom, x2a, by2a, x2, by2); + path.lineTo(x3, by3); + path.cubicTo(x3a, by3a, x3a, ty3a, x3, ty3); + path.lineTo(x2, ty2); + path.cubicTo(x2a, ty2a, x1a, bounds.top, x1, bounds.top); + path.close(); } } 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 cc6195f2c..545691ae8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -19,7 +21,11 @@ import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.provider.Settings; +import android.text.Layout; +import android.text.StaticLayout; +import android.util.LongSparseArray; import android.util.Property; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -27,6 +33,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; @@ -58,6 +65,7 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.messenger.support.LongSparseLongArray; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AlertDialog; @@ -72,6 +80,8 @@ import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; import org.telegram.ui.PremiumPreviewFragment; +import org.telegram.ui.SelectAnimatedEmojiDialog; +import org.telegram.ui.Stories.recorder.HintView2; import java.util.ArrayList; import java.util.HashSet; @@ -102,6 +112,34 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public final RecyclerListView recyclerListView; public final float durationScale; + private static final int VIEW_TYPE_REACTION = 0; + private static final int VIEW_TYPE_PREMIUM_BUTTON = 1; + private static final int VIEW_TYPE_CUSTOM_EMOJI_BUTTON = 2; + private static final int VIEW_TYPE_CUSTOM_REACTION = 3; + + public ArrayList items = new ArrayList<>(); + public ArrayList oldItems = new ArrayList<>(); + + class InnerItem extends AdapterWithDiffUtils.Item { + ReactionsLayoutInBubble.VisibleReaction reaction; + + public InnerItem(int viewType, ReactionsLayoutInBubble.VisibleReaction reaction) { + super(viewType, false); + this.reaction = reaction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InnerItem innerItem = (InnerItem) o; + if (viewType == innerItem.viewType && (viewType == VIEW_TYPE_REACTION || viewType == VIEW_TYPE_CUSTOM_REACTION)) { + return reaction != null && reaction.equals(innerItem.reaction); + } + return viewType == innerItem.viewType; + } + } + private Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint leftShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG), rightShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -109,10 +147,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private float transitionProgress = 1f; public RectF rect = new RectF(); private Path mPath = new Path(); - public float radius = AndroidUtilities.dp(72); - private float bigCircleRadius = AndroidUtilities.dp(8); + public float radius = dp(72); + private float bigCircleRadius = dp(8); private float smallCircleRadius = bigCircleRadius / 2; - public int bigCircleOffset = AndroidUtilities.dp(36); + public int bigCircleOffset = dp(36); private MessageObject messageObject; private int currentAccount; private long waitingLoadingChatId; @@ -179,9 +217,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public boolean skipEnterAnimation; public boolean isHiddenNextReaction = true; private Runnable onSwitchedToLoopView; - private boolean hasHint; + public boolean hasHint; public TextView hintView; - private float bubblesOffset; + public int hintViewWidth, hintViewHeight; + public float bubblesOffset; public ReactionsContainerLayout(int type, BaseFragment fragment, @NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -203,7 +242,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio animationEnabled = SharedConfig.animationsEnabled() && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; shadow = ContextCompat.getDrawable(context, R.drawable.reactions_bubble_shadow).mutate(); - shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7); + shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = dp(7); shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow), PorterDuff.Mode.MULTIPLY)); recyclerListView = new RecyclerListView(context) { @@ -289,14 +328,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (!showCustomEmojiReaction()) { int position = parent.getChildAdapterPosition(view); if (position == 0) { - outRect.left = AndroidUtilities.dp(6); + outRect.left = dp(6); } - outRect.right = AndroidUtilities.dp(4); + outRect.right = dp(4); if (position == listAdapter.getItemCount() - 1) { if (showUnlockPremiumButton() || showCustomEmojiReaction()) { - outRect.right = AndroidUtilities.dp(2); + outRect.right = dp(2); } else { - outRect.right = AndroidUtilities.dp(6); + outRect.right = dp(6); } } } else { @@ -331,7 +370,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); premiumLockIconView.setScaleX(0f); premiumLockIconView.setScaleY(0f); - premiumLockIconView.setPadding(AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1)); + premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); premiumLockIconView.setOnClickListener(v -> { int[] position = new int[2]; @@ -350,8 +389,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } else { customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); } - customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); - customEmojiReactionsIconView.setPadding(AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); customEmojiReactionsIconView.setOnClickListener(v -> { @@ -361,8 +400,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio break; } - int size = getLayoutParams().height - (hasHint ? AndroidUtilities.dp(20) : 0) - getPaddingTop() - getPaddingBottom(); - view.setLayoutParams(new RecyclerView.LayoutParams(size - AndroidUtilities.dp(12), size)); + int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); + view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); return new RecyclerListView.Holder(view); } @@ -376,6 +415,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } } + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + int position = holder.getAdapterPosition(); + if (position >= 0 && position < items.size()) { + ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); + } + } + super.onViewAttachedToWindow(holder); + } + @Override public int getItemCount() { return items.size(); @@ -386,14 +436,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio return items.get(position).viewType; } - ArrayList items = new ArrayList<>(); - ArrayList oldItems = new ArrayList<>(); - - private static final int VIEW_TYPE_REACTION = 0; - private static final int VIEW_TYPE_PREMIUM_BUTTON = 1; - private static final int VIEW_TYPE_CUSTOM_EMOJI_BUTTON = 2; - private static final int VIEW_TYPE_CUSTOM_REACTION = 3; - @Override public void notifyDataSetChanged() { oldItems.clear(); @@ -411,28 +453,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } setItems(oldItems, items); } - - class InnerItem extends AdapterWithDiffUtils.Item { - - ReactionsLayoutInBubble.VisibleReaction reaction; - - public InnerItem(int viewType, ReactionsLayoutInBubble.VisibleReaction reaction) { - super(viewType, false); - this.reaction = reaction; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - InnerItem innerItem = (InnerItem) o; - if (viewType == innerItem.viewType && (viewType == VIEW_TYPE_REACTION || viewType == VIEW_TYPE_CUSTOM_REACTION)) { - return reaction != null && reaction.equals(innerItem.reaction); - } - return viewType == innerItem.viewType; - } - - } }); recyclerListView.addOnScrollListener(new LeftRightShadowsListener()); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -474,9 +494,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { int i = parent.getChildAdapterPosition(view); if (i == 0) - outRect.left = AndroidUtilities.dp(8); + outRect.left = dp(8); if (i == listAdapter.getItemCount() - 1) { - outRect.right = AndroidUtilities.dp(8); + outRect.right = dp(8); } } }); @@ -500,7 +520,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio invalidateShaders(); int size = recyclerListView.getLayoutParams().height - recyclerListView.getPaddingTop() - recyclerListView.getPaddingBottom(); - nextRecentReaction.getLayoutParams().width = size - AndroidUtilities.dp(12); + nextRecentReaction.getLayoutParams().width = size - dp(12); nextRecentReaction.getLayoutParams().height = size; if (type == TYPE_STORY_LIKES) { @@ -515,6 +535,16 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio return showExpandableReactions; } + public int getWindowType() { + if (type == TYPE_TAGS) { + return SelectAnimatedEmojiDialog.TYPE_TAGS; + } + if (showExpandableReactions) { + return SelectAnimatedEmojiDialog.TYPE_EXPANDABLE_REACTIONS; + } + return SelectAnimatedEmojiDialog.TYPE_REACTIONS; + } + private void animatePullingBack() { if (pullingLeftOffset != 0) { pullingDownBackAnimator = ValueAnimator.ofFloat(pullingLeftOffset, 0); @@ -535,7 +565,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public void dismissWindow() { - reactionsWindow.dismiss(); + if (reactionsWindow != null) { + reactionsWindow.dismiss(); + } } public CustomEmojiReactionsWindow getReactionsWindow() { @@ -555,9 +587,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio delegate.onEmojiWindowDismissed(); } }); + onShownCustomEmojiReactionDialog(); //animatePullingBack(); } + protected void onShownCustomEmojiReactionDialog(){ + + } + private void invalidateLoopViews() { for (int i = 0; i < recyclerListView.getChildCount(); i++) { View child = recyclerListView.getChildAt(i); @@ -612,7 +649,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio this.visibleReactionsList.clear(); if (showCustomEmojiReaction()) { int i = 0; - int n = (AndroidUtilities.displaySize.x - AndroidUtilities.dp(36)) / AndroidUtilities.dp(34); + int n = (AndroidUtilities.displaySize.x - dp(36)) / dp(34); if (n > 7) { n = 7; } @@ -637,8 +674,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio allReactionsList.clear(); allReactionsList.addAll(visibleReactionsList); // checkPremiumReactions(this.visibleReactionsList); - int size = getLayoutParams().height - (hasHint ? AndroidUtilities.dp(20) : 0) - getPaddingTop() - getPaddingBottom(); - if (size * visibleReactionsList.size() < AndroidUtilities.dp(200)) { + int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); + if (size * visibleReactionsList.size() < dp(200)) { getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; } @@ -708,7 +745,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio chatScrimPopupContainerLayout.setExpandSize(expandSize); } float transitionLeftOffset = (getWidth() - getPaddingRight()) * Math.min(1f, lt); - float hintHeight = (hasHint ? AndroidUtilities.dp(20) : 0); + float hintHeight = getTopOffset(); rect.set(getPaddingLeft() + transitionLeftOffset, getPaddingTop() + recyclerListView.getMeasuredHeight() * (1f - otherViewsScale) - expandSize, (getWidth() - getPaddingRight()) * rt, getHeight() - getPaddingBottom() + expandSize); radius = ((rect.height() - hintHeight) - expandSize * 2f) / 2f; @@ -805,7 +842,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } if (pullingLeftOffsetProgress > 0) { float progress = getPullingLeftProgress(); - int reactionSize = nextRecentReaction.getMeasuredWidth() - AndroidUtilities.dp(2); + int reactionSize = nextRecentReaction.getMeasuredWidth() - dp(2); int left = lastReactionX + reactionSize; float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - nextRecentReaction.getMeasuredWidth()), 1f, 0f); float pullingOffsetX = leftProgress * progress * reactionSize; @@ -820,9 +857,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio nextRecentReaction.setScaleY(scale); float additionalOffset = 0; if (type != TYPE_STORY && type != TYPE_STORY_LIKES) { - additionalOffset = - AndroidUtilities.dp(20); + additionalOffset = - dp(20); } else { - additionalOffset = - AndroidUtilities.dp(8); + additionalOffset = - dp(8); } nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX + additionalOffset); if (nextRecentReaction.getVisibility() != View.VISIBLE) { @@ -887,12 +924,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (isTop) { canvas.clipRect(0, 0, getMeasuredWidth(), AndroidUtilities.lerp(rect.top, getMeasuredHeight(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) + 1); } else { - canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) - 1, getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + AndroidUtilities.dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress))); + canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) - 1, getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress))); } float cx = LocaleController.isRTL || mirrorX ? bigCircleOffset : getWidth() - bigCircleOffset; cx += bubblesOffset; float cy = isTop ? getPaddingTop() - expandSize() : getHeight() - getPaddingBottom() + expandSize(); - int sPad = AndroidUtilities.dp(3); + int sPad = dp(3); shadow.setAlpha(alpha); bgPaint.setAlpha(alpha); shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr)); @@ -906,9 +943,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio cx = LocaleController.isRTL || mirrorX ? bigCircleOffset - bigCircleRadius : getWidth() - bigCircleOffset + bigCircleRadius; cx += bubblesOffset; - cy = isTop ? getPaddingTop() - expandSize() - AndroidUtilities.dp(16) : getHeight() - smallCircleRadius - sPad + expandSize(); + cy = isTop ? getPaddingTop() - expandSize() - dp(16) : getHeight() - smallCircleRadius - sPad + expandSize(); cy = AndroidUtilities.lerp(cy, smallCircleRadius + sPad - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)); - sPad = -AndroidUtilities.dp(1); + sPad = -dp(1); shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr)); shadow.draw(canvas); if (delegate.drawBackground()) { @@ -943,8 +980,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio float pullingOffsetX = 0; if (pullingLeftOffset != 0) { float progress = getPullingLeftProgress(); - float leftProgress = Utilities.clamp(view.getLeft() / (float) (getMeasuredWidth() - AndroidUtilities.dp(34)), 1f, 0f); - pullingOffsetX = leftProgress * progress * AndroidUtilities.dp(46); + float leftProgress = Utilities.clamp(view.getLeft() / (float) (getMeasuredWidth() - dp(34)), 1f, 0f); + pullingOffsetX = leftProgress * progress * dp(46); } if (view.currentReaction.equals(pressedReaction)) { View imageView = view.loopImageView.getVisibility() == View.VISIBLE ? view.loopImageView : view.enterImageView; @@ -1012,7 +1049,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public float getPullingLeftProgress() { - return Utilities.clamp(pullingLeftOffset / AndroidUtilities.dp(42), 2f, 0f); + return Utilities.clamp(pullingLeftOffset / dp(42), 2f, 0f); } @Override @@ -1025,7 +1062,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio * Invalidates shaders */ private void invalidateShaders() { - int dp = AndroidUtilities.dp(24); + int dp = dp(24); float cy = getHeight() / 2f; int clr = Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground); leftShadowPaint.setShader(new LinearGradient(0, cy, dp, cy, clr, Color.TRANSPARENT, Shader.TileMode.CLAMP)); @@ -1090,6 +1127,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } filterReactions(visibleReactions); showExpandableReactions = !allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + if (type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium()) { + showExpandableReactions = false; + } setVisibleReactionsList(visibleReactions); if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { @@ -1118,6 +1158,74 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio listAdapter.notifyDataSetChanged(); } + public void setSelectedReactions(ArrayList messages) { + selectedReactions.clear(); + for (int a = 0; a < messages.size(); ++a) { + MessageObject message = messages.get(a); + if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { + for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { + if (message.messageOwner.reactions.results.get(i).chosen) { + selectedReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.messageOwner.reactions.results.get(i).reaction)); + } + } + } + } + listAdapter.notifyDataSetChanged(); + } + + public HashSet getSelectedReactions() { + return selectedReactions; + } + + public static HashSet getInclusiveReactions(ArrayList messages) { + LongSparseArray arr = new LongSparseArray<>(); + HashSet messageReactions = new HashSet<>(); + boolean firstMessage = true; + for (int k = 0; k < messages.size(); ++k) { + MessageObject message = messages.get(k); + messageReactions.clear(); + if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { + for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { + if (message.messageOwner.reactions.results.get(i).chosen) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.messageOwner.reactions.results.get(i).reaction); + if (firstMessage || arr.indexOfKey(reaction.hash) >= 0) { + messageReactions.add(reaction.hash); + arr.put(reaction.hash, reaction); + } + } + } + } + firstMessage = false; + for (int j = 0; j < arr.size(); ++j) { + if (!messageReactions.contains(arr.keyAt(j))) { + arr.removeAt(j); + j--; + } + } + } + HashSet selectedReactions = new HashSet<>(); + for (int j = 0; j < arr.size(); ++j) { + selectedReactions.add(arr.valueAt(j)); + } + return selectedReactions; + } + + public void setSelectedReactionsInclusive(ArrayList messages) { + selectedReactions.clear(); + selectedReactions.addAll(getInclusiveReactions(messages)); + updateSelected(); + } + + private void updateSelected() { + AndroidUtilities.forEachViews(recyclerListView, child -> { + int position = recyclerListView.getChildAdapterPosition(child); + if (position < 0 || position >= items.size()) return; + if (child instanceof ReactionHolderView) { + ((ReactionHolderView) child).updateSelected(items.get(position).reaction); + } + }); + } + private void filterReactions(List visibleReactions) { HashSet set = new HashSet<>(); for (int i = 0; i < visibleReactions.size(); i++) { @@ -1166,7 +1274,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio HashSet hashSet = new HashSet<>(); int added = 0; if (type == TYPE_TAGS) { - TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(); + TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(0); if (savedTags != null) { for (int i = 0; i < savedTags.tags.size(); i++) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(savedTags.tags.get(i).reaction); @@ -1175,21 +1283,22 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio visibleReactions.add(visibleReaction); added++; } - if (added == 16) { - break; - } +// if (added == 16) { +// break; +// } } } - } - for (int i = 0; i < topReactions.size(); i++) { - ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(topReactions.get(i)); - if (!hashSet.contains(visibleReaction) && (type == TYPE_TAGS || UserConfig.getInstance(currentAccount).isPremium() || visibleReaction.documentId == 0)) { - hashSet.add(visibleReaction); - visibleReactions.add(visibleReaction); - added++; - } - if (added == 16) { - break; + } else { + for (int i = 0; i < topReactions.size(); i++) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(topReactions.get(i)); + if (!hashSet.contains(visibleReaction) && (type == TYPE_TAGS || UserConfig.getInstance(currentAccount).isPremium() || visibleReaction.documentId == 0)) { + hashSet.add(visibleReaction); + visibleReactions.add(visibleReaction); + added++; + } + // if (added == 16) { + // break; + // } } } @@ -1257,11 +1366,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public int getTotalWidth() { int itemsCount = getItemsCount(); + int width; if (!showCustomEmojiReaction()) { - return AndroidUtilities.dp(36) * itemsCount + AndroidUtilities.dp(2) * (itemsCount - 1) + AndroidUtilities.dp(16); + width = dp(36) * itemsCount + dp(2) * (itemsCount - 1) + dp(16); } else { - return AndroidUtilities.dp(36) * itemsCount - AndroidUtilities.dp(4); + width = dp(36) * itemsCount - dp(4); } + return width; + } + + public int getHintTextWidth() { + return hintViewWidth; } public int getItemsCount() { @@ -1298,7 +1413,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public void setCustomEmojiReactionsBackground(boolean isNeed) { if (isNeed) { - customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); } else { customEmojiReactionsIconView.setBackground(null); } @@ -1404,18 +1519,64 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio invalidate(); } - public void setHint(String storyReactionsHint) { + public void setHint(CharSequence storyReactionsHint) { hasHint = true; - hintView = new TextView(getContext()); - hintView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); - hintView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + if (hintView == null) { + hintView = new LinkSpanDrawable.LinksTextView(getContext(), resourcesProvider); + hintView.setPadding(dp(8), 0, dp(8), 0); + hintView.setClickable(true); + hintView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { + hintView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + hintView.setAlpha(0.5f); + } else { + hintView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); + } + hintView.setGravity(Gravity.CENTER_HORIZONTAL); + addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 6, 0, 0)); + } hintView.setText(storyReactionsHint); - hintView.setAlpha(0.5f); - hintView.setGravity(Gravity.CENTER_HORIZONTAL); - addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 6, 0, 0)); + hintMeasured = false; - ((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = AndroidUtilities.dp(20); - ((LayoutParams) recyclerListView.getLayoutParams()).topMargin = AndroidUtilities.dp(20); + ((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = dp(20); + ((LayoutParams) recyclerListView.getLayoutParams()).topMargin = dp(20); + } + + + private boolean hintMeasured; + public void measureHint() { + if (hintMeasured || !hasHint || getMeasuredWidth() <= 0) return; + + int maxWidth = Math.min(dp(320), getMeasuredWidth() - dp(16)); + StaticLayout layout = new StaticLayout(hintView.getText(), hintView.getPaint(), maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + hintViewHeight = layout.getHeight(); + hintViewWidth = 0; + for (int i = 0; i < layout.getLineCount(); ++i) { + hintViewWidth = Math.max(hintViewWidth, (int) Math.ceil(layout.getLineWidth(i))); + } + if (layout.getLineCount() > 1 && !hintView.getText().toString().contains("\n")) { + maxWidth = HintView2.cutInFancyHalf(hintView.getText(), hintView.getPaint()); + layout = new StaticLayout(hintView.getText(), hintView.getPaint(), maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + hintViewHeight = layout.getHeight(); + hintViewWidth = 0; + for (int i = 0; i < layout.getLineCount(); ++i) { + hintViewWidth = Math.max(hintViewWidth, (int) Math.ceil(layout.getLineWidth(i))); + } + hintView.setPadding(dp(24), 0, dp(24), 0); + hintView.setWidth(dp(48) + maxWidth); + } else { + hintView.setWidth(dp(16) + maxWidth); + } + + int margin = Math.max(dp(20), dp(7) + hintViewHeight); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { + margin = dp(20); + } else { + getLayoutParams().height = dp(52) + margin + dp(22); + } + ((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = margin; + ((LayoutParams) recyclerListView.getLayoutParams()).topMargin = margin; + hintMeasured = true; } public void setTop(boolean isTop) { @@ -1423,7 +1584,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public float getTopOffset() { - return hasHint ? AndroidUtilities.dp(20) : 0; + return hasHint ? ((LayoutParams) recyclerListView.getLayoutParams()).topMargin : 0; } public void setBubbleOffset(float v) { @@ -1482,6 +1643,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public BackupImageView pressedBackupImageView; private ImageReceiver preloadImageReceiver = new ImageReceiver(); public ReactionsLayoutInBubble.VisibleReaction currentReaction; + public PremiumLockIconView lockIconView; public float sideScale = 1f; private boolean isEnter; public boolean hasEnterAnimation; @@ -1655,6 +1817,25 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio pressedBackupImageView.setLayerNum(Integer.MAX_VALUE); } + + public boolean isLocked; + + public void updateSelected(ReactionsLayoutInBubble.VisibleReaction react) { + boolean wasSelected = selected; + selected = selectedReactions.contains(react); + if (selected != wasSelected) { + if (selected) { + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(26); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(26); + } else { + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(34); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(34); + } + requestLayout(); + invalidate(); + } + } + private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int position) { if (currentReaction != null && currentReaction.equals(react)) { this.position = position; @@ -1662,6 +1843,18 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio updateImage(react); return; } + + isLocked = type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium(); + if (isLocked && lockIconView == null) { + lockIconView = new PremiumLockIconView(getContext(), PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED); + lockIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + lockIconView.setImageReceiver(loopImageView.getImageReceiver()); + addView(lockIconView, LayoutHelper.createFrame(18, 18, Gravity.CENTER, 8, 8, 0, 0)); + } + if (lockIconView != null) { + lockIconView.setVisibility(isLocked ? View.VISIBLE : View.GONE); + } + resetAnimation(); currentReaction = react; selected = selectedReactions.contains(react); @@ -1673,15 +1866,26 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (enterImageView.getImageReceiver().getLottieAnimation() != null) { enterImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); } + if (lockIconView != null) { + lockIconView.setAnimatedEmojiDrawable(null); + } } else { pressedBackupImageView.getImageReceiver().clearImage(); loopImageView.getImageReceiver().clearImage(); AnimatedEmojiDrawable pressedDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_LARGE, currentAccount, currentReaction.documentId); - pressedDrawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); pressedBackupImageView.setAnimatedEmojiDrawable(pressedDrawable); AnimatedEmojiDrawable loopDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, currentAccount, currentReaction.documentId); - loopDrawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { + pressedDrawable.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + loopDrawable.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + } else { + pressedDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + loopDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + } loopImageView.setAnimatedEmojiDrawable(loopDrawable); + if (lockIconView != null) { + lockIconView.setAnimatedEmojiDrawable(loopDrawable); + } } setFocusable(true); shouldSwitchToLoopView = hasEnterAnimation;// && !allReactionsIsDefault; @@ -1695,11 +1899,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio loopImageView.setVisibility(View.GONE); } if (selected) { - loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = AndroidUtilities.dp(26); - enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = AndroidUtilities.dp(26); + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(26); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(26); } else { - loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = AndroidUtilities.dp(34); - enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = AndroidUtilities.dp(34); + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(34); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(34); } } @@ -1727,6 +1931,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio preloadImageReceiver.setAllowStartLottieAnimation(false); MediaDataController.getInstance(currentAccount).preloadImage(preloadImageReceiver, ImageLocation.getForDocument(defaultReaction.around_animation), ReactionsEffectOverlay.getFilterForAroundAnimation()); } + if (lockIconView != null) { + lockIconView.setImageReceiver(loopImageView.getImageReceiver()); + } } } @@ -1833,17 +2040,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio @Override public boolean onTouchEvent(MotionEvent event) { - if (!touchable) { - return false; - } - if (cancelPressedAnimation != null) { + if (!touchable || cancelPressedAnimation != null) { return false; } if (event.getAction() == MotionEvent.ACTION_DOWN) { pressed = true; pressedX = event.getX(); pressedY = event.getY(); - if (sideScale == 1f) { + if (sideScale == 1f && !isLocked && type != TYPE_TAGS) { AndroidUtilities.runOnUIThread(longPressRunnable, ViewConfiguration.getLongPressTimeout()); } } @@ -1871,13 +2075,13 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio @Override protected void dispatchDraw(Canvas canvas) { if (selected && drawSelected) { - canvas.drawCircle(getMeasuredWidth() >> 1, getMeasuredHeight() >> 1, (getMeasuredWidth() >> 1) - AndroidUtilities.dp(1), selectedPaint); + canvas.drawCircle(getMeasuredWidth() >> 1, getMeasuredHeight() >> 1, (getMeasuredWidth() >> 1) - dp(1), selectedPaint); } if (loopImageView.animatedEmojiDrawable != null && loopImageView.animatedEmojiDrawable.getImageReceiver() != null) { if (position == 0) { - loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(AndroidUtilities.dp(6), 0, 0, AndroidUtilities.dp(6)); + loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(dp(6), 0, 0, dp(6)); } else { - loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(selected ? AndroidUtilities.dp(6) : 0); + loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(selected ? dp(6) : 0); } } super.dispatchDraw(canvas); @@ -2088,7 +2292,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public float expandSize() { - return (int) (getPullingLeftProgress() * AndroidUtilities.dp(6)); + return (int) (getPullingLeftProgress() * dp(6)); } public void setParentLayout(ChatScrimPopupContainerLayout layout) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java index bb13929e7..ac65f1497 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java @@ -1,60 +1,105 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.cancelRunOnUIThread; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.lerp; +import static org.telegram.messenger.AndroidUtilities.runOnUIThread; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.app.Activity; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.InputType; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.CharacterStyle; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.util.Log; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.collection.LongSparseArray; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.AlertDialogDecor; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; -import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; import java.util.HashSet; -import java.util.Objects; public class SearchTagsList extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate { private final int currentAccount; + private final BaseFragment fragment; private final Theme.ResourcesProvider resourcesProvider; public final RecyclerListView listView; private final Adapter adapter; + private LinearLayout premiumLayout; + private long chosen; private final ArrayList oldItems = new ArrayList<>(); private final ArrayList items = new ArrayList<>(); + private boolean shownPremiumLayout; private static class Item { ReactionsLayoutInBubble.VisibleReaction reaction; int count; + String name; + int nameHash; - public static Item get(ReactionsLayoutInBubble.VisibleReaction reaction, int count) { + public static Item get(ReactionsLayoutInBubble.VisibleReaction reaction, int count, String name) { Item item = new Item(); item.reaction = reaction; item.count = count; + item.name = name; + item.nameHash = name == null ? -233 : name.hashCode(); return item; } @@ -68,17 +113,130 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe return false; } Item that = (Item) obj; - return this.count == that.count && this.reaction.hash == that.reaction.hash; + return this.count == that.count && this.reaction.hash == that.reaction.hash && this.nameHash == that.nameHash; } } - public SearchTagsList(Context context, SizeNotifierFrameLayout contentView, int currentAccount, Theme.ResourcesProvider resourcesProvider) { + public void setChosen(ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean notify) { + if (visibleReaction == null) { + chosen = 0; + if (notify) { + setFilter(null); + } + adapter.notifyDataSetChanged(); + return; + } + for (int i = 0; i < items.size(); i++) { + SearchTagsList.Item item = items.get(i); + if (visibleReaction.hash == item.reaction.hash) { + chosen = item.hash(); + if (notify) { + setFilter(item.reaction); + } + adapter.notifyDataSetChanged(); + listView.scrollToPosition(i); + break; + } + } + } + + private void createPremiumLayout() { + if (premiumLayout != null) { + return; + } + + premiumLayout = new LinearLayout(getContext()); + premiumLayout.setOnClickListener(v -> { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + }); + premiumLayout.setOrientation(LinearLayout.HORIZONTAL); + ScaleStateListAnimator.apply(premiumLayout, 0.03f, 1.25f); + + TextView tagView = new TextView(getContext()) { + private final Path path = new Path(); + private final RectF bounds = new RectF(); + private final Paint paint = new Paint(); + @Override + protected void dispatchDraw(Canvas canvas) { + paint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider), 0.10f)); + bounds.set(0, 0, getWidth(), getHeight()); + ReactionsLayoutInBubble.fillTagPath(bounds, path); + canvas.drawPath(path, paint); + super.dispatchDraw(canvas); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + int left = getWidth(), right = 0; + for (int i = 0; i < getChildCount(); ++i) { + left = Math.min(left, getChildAt(i).getLeft()); + right = Math.max(right, getChildAt(i).getRight()); + } + setPivotX((left + right) / 2f); + } + }; + tagView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)); + tagView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + tagView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + SpannableStringBuilder ssb = new SpannableStringBuilder(); + Drawable lockDrawable = getContext().getResources().getDrawable(R.drawable.msg_mini_lock3).mutate(); + lockDrawable.setColorFilter(new PorterDuffColorFilter(Theme.key_chat_messageLinkIn, PorterDuff.Mode.SRC_IN)); + ColoredImageSpan span = new ColoredImageSpan(lockDrawable); + span.setTranslateY(0); + span.setTranslateX(0); + span.setScale(.94f, .94f); + SpannableString lock = new SpannableString("l"); + lock.setSpan(span, 0, lock.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ssb.append(lock); + ssb.append(" ").append(LocaleController.getString(R.string.AddTagsToYourSavedMessages1)); + tagView.setText(ssb); + tagView.setPadding(dp(4), dp(4), dp(9), dp(4)); + + TextView textView = new TextView(getContext()); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + ssb = new SpannableStringBuilder(LocaleController.getString(R.string.AddTagsToYourSavedMessages2)); + SpannableString arrow = new SpannableString(">"); + Drawable imageDrawable = getContext().getResources().getDrawable(R.drawable.msg_arrowright).mutate(); + imageDrawable.setColorFilter(new PorterDuffColorFilter(Theme.key_chat_messageLinkIn, PorterDuff.Mode.SRC_IN)); + span = new ColoredImageSpan(imageDrawable); + span.setScale(.76f, .76f); + span.setTranslateX(-dp(1)); + span.setTranslateY(dp(1)); + arrow.setSpan(span, 0, arrow.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ssb.append(arrow); + textView.setText(ssb); + textView.setPadding(dp(5.66f), dp(4), dp(9), dp(4)); + + premiumLayout.addView(tagView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); + premiumLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); + + addView(premiumLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.FILL_HORIZONTAL, 16.33f, 0, 16.33f, 0)); + } + + private long topicId; + + public SearchTagsList(Context context, BaseFragment fragment, SizeNotifierFrameLayout contentView, int currentAccount, long topicId, Theme.ResourcesProvider resourcesProvider, boolean showWithCut) { super(context, contentView); + this.showWithCut = showWithCut; this.currentAccount = currentAccount; + this.fragment = fragment; this.resourcesProvider = resourcesProvider; + this.topicId = topicId; + ReactionsLayoutInBubble.initPaints(resourcesProvider); listView = new RecyclerListView(context, resourcesProvider) { + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (premiumLayout != null && premiumLayout.getAlpha() > 0.5f) { + return false; + } + return super.dispatchTouchEvent(ev); + } + @Override public Integer getSelectorColor(int position) { return 0; @@ -90,59 +248,291 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe layoutManager.setOrientation(RecyclerView.HORIZONTAL); listView.setLayoutManager(layoutManager); listView.setAdapter(adapter = new Adapter()); - addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listView.setOverScrollMode(OVER_SCROLL_NEVER); + addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); listView.setOnItemClickListener((view, position) -> { if (position < 0 || position >= items.size()) { return; } + if (!UserConfig.getInstance(currentAccount).isPremium()) { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } + long hash = items.get(position).hash(); + if (!setFilter(chosen == hash ? null : items.get(position).reaction)) { + return; + } + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + if (child == view) { + if (i <= 1) { + listView.smoothScrollBy(-dp(i == 0 ? 90 : 50), 0); + } else if (i >= listView.getChildCount() - 2) { + listView.smoothScrollBy(dp((i == listView.getChildCount() - 1) ? 80 : 50), 0); + } + } + } listView.forAllChild(view2 -> { if (view2 instanceof TagButton) { ((TagButton) view2).setChosen(false, true); } }); - long hash = items.get(position).hash(); if (chosen == hash) { chosen = 0; - setFilter(null); } else { chosen = hash; - setFilter(items.get(position).reaction); ((TagButton) view).setChosen(true, true); } }); + listView.setOnItemLongClickListener((view, position) -> { + if (position < 0 || position >= items.size() || !UserConfig.getInstance(currentAccount).isPremium()) + return false; + if (!UserConfig.getInstance(currentAccount).isPremium()) { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return true; + } + TagButton btn = (TagButton) view; + if (btn.reactionButton != null) { + btn.reactionButton.startAnimation(); + } + final Item item = items.get(position); + ItemOptions.makeOptions(fragment, view) + .setGravity(Gravity.LEFT) + .add(R.drawable.menu_tag_rename, LocaleController.getString(TextUtils.isEmpty(item.name) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag), () -> { + openRenameTagAlert(getContext(), currentAccount, item.reaction.toTLReaction(), resourcesProvider, false); + }) + .show(); + return true; + }); DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { @Override - public boolean animateMove(RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY, int toX, int toY) { - int position = holder.getAdapterPosition(); - if (position >= 0 && position < items.size()) { - Item item = items.get(position); - TagButton btn = (TagButton) holder.itemView; - boolean updatedChosen = btn.setChosen(chosen == item.hash(), true); - boolean updatedCount = btn.setCount(item.count); - if (updatedChosen || updatedCount) { - return true; - } - } - return super.animateMove(holder, info, fromX, fromY, toX, toY); + public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { + return true; } - @Override - protected void animateMoveImpl(RecyclerView.ViewHolder holder, MoveInfo moveInfo) { - super.animateMoveImpl(holder, moveInfo); + public boolean animateMove(RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + if (view instanceof TagButton) { + ((TagButton) view).startAnimate(); + } + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + checkIsRunning(); + return true; } }; - itemAnimator.setSupportsChangeAnimations(false); itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); itemAnimator.setDurations(320); listView.setItemAnimator(itemAnimator); MediaDataController.getInstance(currentAccount).loadSavedReactions(false); - updateTags(); + updateTags(false); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == listView && premiumLayout != null) { + if (premiumLayout.getAlpha() >= 1f) + return false; + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * (1f - premiumLayout.getAlpha())), Canvas.ALL_SAVE_FLAG); + boolean r = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return r; + } + return super.drawChild(canvas, child, drawingTime); + } + + private static AlertDialog currentDialog; + public static boolean onBackPressedRenameTagAlert() { + if (currentDialog != null) { + currentDialog.dismiss(); + currentDialog = null; + return true; + } + return false; + } + public static void openRenameTagAlert(Context context, int currentAccount, TLRPC.Reaction reaction, Theme.ResourcesProvider resourcesProvider, boolean forceNotAdaptive) { + Activity activity = AndroidUtilities.findActivity(context); + View currentFocus = activity != null ? activity.getCurrentFocus() : null; + final boolean adaptive = currentFocus instanceof EditText && !forceNotAdaptive; + AlertDialog[] dialog = new AlertDialog[1]; + AlertDialog.Builder builder; + if (adaptive) { + builder = new AlertDialogDecor.Builder(context, resourcesProvider); + } else { + builder = new AlertDialog.Builder(context, resourcesProvider); + } + String[] hintText = new String[1]; + String name = MessagesController.getInstance(currentAccount).getSavedTagName(reaction); + builder.setTitle(new SpannableStringBuilder(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction).toCharSequence(20)).append(" ").append(LocaleController.getString(TextUtils.isEmpty(name) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag))); + + final int MAX_NAME_LENGTH = 12; + EditTextBoldCursor editText = new EditTextBoldCursor(context) { + AnimatedColor limitColor = new AnimatedColor(this); + private int limitCount; + AnimatedTextView.AnimatedTextDrawable limit = new AnimatedTextView.AnimatedTextDrawable(false, true, true); { + limit.setAnimationProperties(.2f, 0, 160, CubicBezierInterpolator.EASE_OUT_QUINT); + limit.setTextSize(dp(15.33f)); + limit.setCallback(this); + limit.setGravity(Gravity.RIGHT); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == limit || super.verifyDrawable(who); + } + + @Override + protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + + if (limit != null) { + limitCount = MAX_NAME_LENGTH - text.length(); + limit.cancelAnimation(); + limit.setText(limitCount > 4 ? "" : "" + limitCount); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + + limit.setTextColor(limitColor.set(Theme.getColor(limitCount < 0 ? Theme.key_text_RedRegular : Theme.key_dialogSearchHint, resourcesProvider))); + limit.setBounds(getScrollX(), 0, getScrollX() + getWidth(), getHeight()); + limit.draw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); + } + }; + editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + String text = editText.getText().toString(); + if (text.length() > MAX_NAME_LENGTH) { + AndroidUtilities.shakeView(editText); + return true; + } + MessagesController.getInstance(currentAccount).renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction), text); + if (dialog[0] != null) { + dialog[0].dismiss(); + } + if (dialog[0] == currentDialog) { + currentDialog = null; + } + if (currentFocus != null) { + currentFocus.requestFocus(); + } + return true; + } + return false; + } + }); + MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(AndroidUtilities.getCurrentKeyboardLanguage(), true); + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + editText.setText(name == null ? "" : name); + editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + editText.setHintColor(Theme.getColor(Theme.key_groupcreate_hintText, resourcesProvider)); + editText.setHintText(LocaleController.getString(R.string.SavedTagLabelPlaceholder)); + editText.setSingleLine(true); + editText.setFocusable(true); + editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); + editText.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField, resourcesProvider), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated, resourcesProvider), Theme.getColor(Theme.key_text_RedRegular, resourcesProvider)); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + editText.setBackgroundDrawable(null); + editText.setPadding(0, 0, dp(42), 0); +// editText.addTextChangedListener(new TextWatcher() { +// boolean ignoreTextChange; +// @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) { +// if (ignoreTextChange) { +// return; +// } +// if (s.length() > MAX_NAME_LENGTH) { +// ignoreTextChange = true; +// s.delete(MAX_NAME_LENGTH, s.length()); +// AndroidUtilities.shakeView(editText); +// editText.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); +// ignoreTextChange = false; +// } +// } +// }); + + LinearLayout container = new LinearLayout(context); + container.setOrientation(LinearLayout.VERTICAL); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setText(LocaleController.getString(R.string.SavedTagLabelTagText)); + container.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 5, 24, 12)); + + container.addView(editText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 10)); + builder.setView(container); + builder.setWidth(dp(292)); + + builder.setPositiveButton(LocaleController.getString(R.string.Save), (dialogInterface, i) -> { + String text = editText.getText().toString(); + if (text.length() > MAX_NAME_LENGTH) { + AndroidUtilities.shakeView(editText); + return; + } + MessagesController.getInstance(currentAccount).renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction), text); + dialogInterface.dismiss(); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialogInterface, i) -> { + dialogInterface.dismiss(); + }); + if (adaptive) { + dialog[0] = currentDialog = builder.create(); + currentDialog.setOnDismissListener(d -> { + currentDialog = null; + currentFocus.requestFocus(); + }); + currentDialog.setOnShowListener(d -> { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + }); + currentDialog.showDelayed(250); + } else { + dialog[0] = builder.create(); + dialog[0].setOnDismissListener(d -> { + AndroidUtilities.hideKeyboard(editText); + }); + dialog[0].setOnShowListener(d -> { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + }); + dialog[0].show(); + } + dialog[0].setDismissDialogByButtons(false); + editText.setSelection(editText.getText().length()); } public boolean hasFilters() { - return !items.isEmpty(); + return !items.isEmpty() || shownPremiumLayout; } public void clear() { @@ -154,68 +544,109 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe chosen = 0; } - protected void setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { - + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + return true; } public void attach() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.savedReactionTagsUpdate); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.emojiLoaded); } public void detach() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.savedReactionTagsUpdate); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.emojiLoaded); } @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.savedReactionTagsUpdate) { - updateTags(); + final long thisTopicId = (long) args[0]; + if (thisTopicId == 0 || thisTopicId == topicId) { + updateTags(true); + } + } else if (id == NotificationCenter.emojiLoaded) { + invalidate(); + AndroidUtilities.forEachViews(listView, View::invalidate); } } - public void updateTags() { + public void updateTags(boolean notify) { HashSet hashes = new HashSet<>(); + oldItems.clear(); oldItems.addAll(items); items.clear(); - TLRPC.TL_messages_savedReactionsTags savedReactionsTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(); + + final MessagesController ms = MessagesController.getInstance(currentAccount); + TLRPC.TL_messages_savedReactionsTags savedReactionsTags = ms.getSavedReactionTags(topicId); + boolean hasChosen = false; + if (savedReactionsTags != null) { for (int i = 0; i < savedReactionsTags.tags.size(); ++i) { TLRPC.TL_savedReactionTag tag = savedReactionsTags.tags.get(i); ReactionsLayoutInBubble.VisibleReaction r = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(tag.reaction); if (!hashes.contains(r.hash)) { - items.add(Item.get(r, tag.count)); + if (topicId != 0 && tag.count <= 0) + continue; + Item item = Item.get(r, tag.count, topicId != 0 ? ms.getSavedTagName(tag.reaction) : tag.title); + if (item.hash() == chosen) { + hasChosen = true; + } + items.add(item); hashes.add(r.hash); } } } -// ArrayList defaultReactions = MediaDataController.getInstance(currentAccount).getSavedReactions(); -// for (int i = 0; i < defaultReactions.size(); ++i) { -// ReactionsLayoutInBubble.VisibleReaction r = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(defaultReactions.get(i)); -// if (!hashes.contains(r.hash)) { -// items.add(Item.get(r, 0)); -// hashes.add(r.hash); -// } -// } - DiffUtil.calculateDiff(new DiffUtil.Callback() { - @Override - public int getOldListSize() { - return oldItems.size(); + if (!hasChosen && chosen != 0) { + chosen = 0; + setFilter(null); + } + + if (notify) { + DiffUtil.calculateDiff(new DiffUtil.Callback() { + @Override + public int getOldListSize() { + return oldItems.size(); + } + + @Override + public int getNewListSize() { + return items.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return oldItems.get(oldItemPosition).hash() == items.get(newItemPosition).hash(); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + return oldItems.get(oldItemPosition).equals(items.get(newItemPosition)); + } + }).dispatchUpdatesTo(adapter); + } else { + adapter.notifyDataSetChanged(); + } + + if (shownPremiumLayout = !UserConfig.getInstance(currentAccount).isPremium()) { + createPremiumLayout(); + if (!notify) { + premiumLayout.setVisibility(View.VISIBLE); + premiumLayout.setAlpha(0f); + premiumLayout.animate().alpha(1f).start(); } - @Override - public int getNewListSize() { - return items.size(); + } else if (premiumLayout != null) { + if (notify) { + premiumLayout.animate().alpha(0f).withEndAction(() -> { + premiumLayout.setVisibility(View.GONE); + }).start(); + } else { + premiumLayout.setAlpha(1f); + premiumLayout.setVisibility(View.VISIBLE); } - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).equals(items.get(newItemPosition)); - } - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).hash() == items.get(newItemPosition).hash(); - } - }).dispatchUpdatesTo(adapter); + } } @Override @@ -231,36 +662,87 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe return super.dispatchTouchEvent(ev); } - private float shownT; + public float shownT; + public boolean showWithCut = true; public void setShown(float shownT) { this.shownT = shownT; listView.setPivotX(listView.getWidth() / 2f); listView.setPivotY(0); listView.setScaleX(lerp(0.8f, 1, shownT)); listView.setScaleY(lerp(0.8f, 1, shownT)); - listView.setAlpha(shownT); + if (showWithCut) { + listView.setAlpha(shownT); + } else { + setAlpha(shownT); + } invalidate(); } + protected void onShownUpdate(boolean finish) { + + } + + private float actionBarTagsT; + private ValueAnimator actionBarTagsAnimator; + public void show(boolean show) { + if (actionBarTagsAnimator != null) { + Animator a = actionBarTagsAnimator; + actionBarTagsAnimator = null; + a.cancel(); + } + if (show) { + setVisibility(View.VISIBLE); + } + actionBarTagsAnimator = ValueAnimator.ofFloat(actionBarTagsT, show ? 1f : 0f); + actionBarTagsAnimator.addUpdateListener(valueAnimator1 -> { + actionBarTagsT = (float) valueAnimator1.getAnimatedValue(); + setShown(actionBarTagsT); + onShownUpdate(false); + }); + actionBarTagsAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + actionBarTagsAnimator.setDuration(320); + actionBarTagsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation != actionBarTagsAnimator) return; + actionBarTagsT = show ? 1f : 0f; + setShown(actionBarTagsT); + if (!show) { + setVisibility(View.GONE); + } + onShownUpdate(true); + } + }); + actionBarTagsAnimator.start(); + } + public boolean shown() { return shownT > 0.5f; } - -// private final Paint backgroundPaint = new Paint(); -// @Override -// public void setBackgroundColor(int color) { -// backgroundPaint.setColor(color); -// } - public int getCurrentHeight() { return (int) (getMeasuredHeight() * shownT); } + private Paint backgroundPaint2; + @Override + public void setBackgroundColor(int color) { + if (SharedConfig.chatBlurEnabled() && super.sizeNotifierFrameLayout != null) { + super.setBackgroundColor(color); + } else { + backgroundPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint2.setColor(color); + } + } + @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); -// canvas.drawRect(0, 0, getWidth(), getCurrentHeight(), backgroundPaint); - canvas.clipRect(0, 0, getWidth(), getCurrentHeight()); + if (showWithCut) { + canvas.clipRect(0, 0, getWidth(), getCurrentHeight()); + } + if (backgroundPaint2 != null) { + canvas.drawRect(0, 0, getWidth(), getCurrentHeight(), backgroundPaint2); + } super.dispatchDraw(canvas); canvas.restore(); } @@ -288,7 +770,16 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (position < 0 || position >= items.size()) return; final Item item = items.get(position); - ((TagButton) holder.itemView).set(item.reaction.toTLReaction(), item.count); + ((TagButton) holder.itemView).set(item); + ((TagButton) holder.itemView).setChosen(item.hash() == chosen, false); + } + + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + super.onViewAttachedToWindow(holder); + int position = holder.getAdapterPosition(); + if (position < 0 || position >= items.size()) return; + final Item item = items.get(position); ((TagButton) holder.itemView).setChosen(item.hash() == chosen, false); } @@ -305,50 +796,93 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe private class TagButton extends View { public ReactionsLayoutInBubble.ReactionButton reactionButton; + private final AnimatedFloat progress = new AnimatedFloat(this, 0, 260, CubicBezierInterpolator.EASE_OUT_QUINT); + private int count; public TagButton(Context context) { super(context); ScaleStateListAnimator.apply(this); } - private int count; - public void set(TLRPC.Reaction reaction, Integer count) { - TLRPC.TL_reactionCount reactionCount = new TLRPC.TL_reactionCount(); - reactionCount.reaction = reaction; - reactionCount.count = this.count = count == null ? 0 : count; + private ReactionsLayoutInBubble.VisibleReaction lastReaction; + public void set(Item item) { + boolean newReactionButton = lastReaction == null || !lastReaction.equals(item.reaction); + if (newReactionButton) { + TLRPC.TL_reactionCount reactionCount = new TLRPC.TL_reactionCount(); + reactionCount.reaction = item.reaction.toTLReaction(); + reactionCount.count = item.count; - reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, currentAccount, this, reactionCount, false, resourcesProvider) { - @Override - protected void updateColors(float progress) { - lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonTextSelected) : Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), progress); - lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReaction, resourcesProvider), progress); - } + reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, currentAccount, this, reactionCount, false, true, resourcesProvider) { + @Override + protected void updateColors(float progress) { + lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonTextSelected, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReactionText, resourcesProvider), progress); + lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReaction, resourcesProvider), progress); + lastDrawnTextColor = Theme.blendOver(lastDrawnBackgroundColor, lastDrawnTextColor); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, chosen ? 0x5affffff : Theme.getColor(Theme.key_actionBarActionModeReactionDot, resourcesProvider), progress); + } - @Override - protected boolean drawTagDot() { - return !drawCounter(); - } + @Override + protected boolean drawTagDot() { + return !drawCounter(); + } - @Override - protected int getCacheType() { - return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS; - } + @Override + protected int getCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_SAVED_REACTION; + } - @Override - protected boolean drawCounter() { - return count > 0 || counterDrawable.countChangeProgress != 1f; - } - }; + @Override + protected boolean drawCounter() { + return count > 0 || hasName || counterDrawable.countChangeProgress != 1f; + } + + @Override + protected boolean drawTextWithCounter() { + return true; + } + }; + reactionButton.counterDrawable.setSize(dp(29), dp(100)); + reactionButton.isTag = true; + } else { + reactionButton.count = item.count; + } + lastReaction = item.reaction; + if (!newReactionButton) { + reactionButton.animateFromWidth = reactionButton.width; + } reactionButton.width = dp(44.33f); - reactionButton.counterDrawable.setCount(reactionCount.count, false); - if (reactionButton.counterDrawable != null && reactionButton.count > 0) { - reactionButton.width += reactionButton.counterDrawable.textPaint.measureText(reactionButton.countText); + reactionButton.hasName = !TextUtils.isEmpty(item.name); + if (reactionButton.hasName) { + reactionButton.textDrawable.setText(Emoji.replaceEmoji(item.name, reactionButton.textDrawable.getPaint().getFontMetricsInt(), false), !newReactionButton); + } else if (reactionButton.textDrawable != null) { + reactionButton.textDrawable.setText("", !newReactionButton); + } + reactionButton.countText = Integer.toString(item.count); + reactionButton.counterDrawable.setCount(item.count, !newReactionButton); + if (reactionButton.counterDrawable != null && (reactionButton.count > 0 || reactionButton.hasName)) { + reactionButton.width += reactionButton.counterDrawable.getCurrentWidth() + dp(reactionButton.hasName ? 4 : 0) + reactionButton.textDrawable.getAnimateToWidth(); + } + if (newReactionButton) { + reactionButton.animateFromWidth = reactionButton.width; } reactionButton.height = dp(28); reactionButton.choosen = chosen; if (attached) { reactionButton.attach(); } + + if (!newReactionButton) { + requestLayout(); + } + } + + public void startAnimate() { + if (reactionButton == null) return; + reactionButton.fromTextColor = reactionButton.lastDrawnTextColor; + reactionButton.fromBackgroundColor = reactionButton.lastDrawnBackgroundColor; + reactionButton.fromTagDotColor = reactionButton.lastDrawnTagDotColor; + progress.set(0, true); + invalidate(); } private boolean chosen; @@ -361,6 +895,7 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe if (animated) { reactionButton.fromTextColor = reactionButton.lastDrawnTextColor; reactionButton.fromBackgroundColor = reactionButton.lastDrawnBackgroundColor; + reactionButton.fromTagDotColor = reactionButton.lastDrawnTagDotColor; progress.set(0, true); } else { progress.set(1, true); @@ -370,30 +905,11 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe return true; } - public boolean setCount(int count) { - if (this.count != count && reactionButton != null) { - reactionButton.animateFromWidth = reactionButton.width; - reactionButton.count = count; - reactionButton.width = dp(44.33f); - reactionButton.counterDrawable.setCount(count, true); - if (reactionButton.counterDrawable != null && reactionButton.count > 0) { - reactionButton.width += reactionButton.counterDrawable.textPaint.measureText(reactionButton.countText); - } - progress.set(0, true); - invalidate(); - return true; - } - return false; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(dp(8.67f) + (reactionButton != null ? reactionButton.width : dp(44.33f)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(40), MeasureSpec.EXACTLY)); } - - private AnimatedFloat progress = new AnimatedFloat(this, 0, 260, CubicBezierInterpolator.EASE_OUT_QUINT); - @Override protected void onDraw(Canvas canvas) { reactionButton.draw(canvas, (getWidth() - reactionButton.width) / 2f, (getHeight() - reactionButton.height) / 2f, progress.set(1f), 1f, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index d134cb85a..18b7175d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -3022,8 +3022,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi TLRPC.Dialog dialog = new TLRPC.TL_dialog(); if (object instanceof TLRPC.User) { dialog.id = ((TLRPC.User) object).id; - } else { + } else if (object instanceof TLRPC.Chat) { dialog.id = -((TLRPC.Chat) object).id; + } else { + return null; } return dialog; } @@ -3042,8 +3044,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi TLRPC.Dialog dialog = new TLRPC.TL_dialog(); if (object instanceof TLRPC.User) { dialog.id = ((TLRPC.User) object).id; - } else { + } else if (object instanceof TLRPC.Chat) { dialog.id = -((TLRPC.Chat) object).id; + } else { + return null; } return dialog; } 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 68688774a..5555fb858 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; import static org.telegram.messenger.MediaDataController.MEDIA_PHOTOVIDEO; import android.animation.Animator; @@ -58,7 +59,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -128,6 +128,7 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.ChatActivityContainer; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; @@ -494,13 +495,56 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter return 0; } float alpha = 0; - if (mediaPages[1] != null && (mediaPages[1].selectedType == TAB_PHOTOVIDEO || mediaPages[1].selectedType == TAB_STORIES || mediaPages[1].selectedType == TAB_ARCHIVED_STORIES)) + if (mediaPages[1] != null && (mediaPages[1].selectedType == TAB_PHOTOVIDEO || mediaPages[1].selectedType == TAB_STORIES || mediaPages[1].selectedType == TAB_ARCHIVED_STORIES || mediaPages[1].selectedType == TAB_SAVED_DIALOGS)) alpha += progress; - if (mediaPages[0] != null && (mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES)) + if (mediaPages[0] != null && (mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES || mediaPages[0].selectedType == TAB_SAVED_DIALOGS)) alpha += 1f - progress; return alpha; } + public float getSearchAlpha(float progress) { + if (isArchivedOnlyStoriesView()) { + return 0; + } + float alpha = 0; + if (mediaPages[1] != null && isSearchItemVisible(mediaPages[1].selectedType) && mediaPages[1].selectedType != TAB_SAVED_DIALOGS) + alpha += progress; + if (mediaPages[0] != null && isSearchItemVisible(mediaPages[0].selectedType) && mediaPages[0].selectedType != TAB_SAVED_DIALOGS) + alpha += 1f - progress; + return alpha; + } + + public void updateSearchItemIcon(float progress) { + if (searchItemIcon == null) { + return; + } + float alpha = 0; + if (mediaPages[1] != null && mediaPages[1].selectedType == TAB_SAVED_DIALOGS) + alpha += progress; + if (mediaPages[0] != null && mediaPages[0].selectedType == TAB_SAVED_DIALOGS) + alpha += 1f - progress; + searchItemIcon.setAlpha(alpha); + searchItemIcon.setScaleX(.85f + .15f * alpha); + searchItemIcon.setScaleY(.85f + .15f * alpha); + searchItemIcon.setVisibility(alpha <= 0.01f ? View.GONE : View.VISIBLE); + } + + public void updateSearchItemIconAnimated() { + if (searchItemIcon == null) { + return; + } + boolean visible = mediaPages[1] != null && mediaPages[1].selectedType == TAB_SAVED_DIALOGS; + if (visible) { + searchItemIcon.setVisibility(View.VISIBLE); + } + searchItemIcon.animate().alpha(visible ? 1f : 0f).scaleX(visible ? 1 : .85f).scaleY(visible ? 1 : .85f).withEndAction(() -> { + if (!visible) { + searchItemIcon.setVisibility(View.GONE); + } + }).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + + public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { boolean show = mediaPage.fastScrollEnabled && isPinnedToTop; View view = mediaPage.listView.getFastScroll(); @@ -562,8 +606,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private GroupUsersSearchAdapter groupUsersSearchAdapter; private MediaPage[] mediaPages = new MediaPage[2]; private ActionBarMenuItem deleteItem; + public ActionBarMenuItem searchItemIcon; private ActionBarMenuItem searchItem; + private float searchAlpha; + private float optionsAlpha; public ImageView photoVideoOptionsItem; + private RLottieImageView optionsSearchImageView; private ActionBarMenuItem forwardItem; private ActionBarMenuItem gotoItem; private ActionBarMenuItem pinItem; @@ -580,6 +628,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private ArrayList audioCellCache = new ArrayList<>(10); private ArrayList audioCache = new ArrayList<>(10); public ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip; + public SearchTagsList searchTagsList; private View shadowLine; private ChatActionCell floatingDateView; private AnimatorSet floatingDateAnimation; @@ -596,6 +645,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private boolean searchWas; private boolean searching; + private ReactionsLayoutInBubble.VisibleReaction searchingReaction; private int[] hasMedia; private int initialTab; @@ -649,6 +699,23 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private ArrayList delegates = new ArrayList<>(); private boolean mediaWasLoaded; + public boolean hasSharedMedia() { + int[] hasMedia = getLastMediaCount(); + if (hasMedia == null) return false; + for (int i = 0; i < hasMedia.length; ++i) { + if (hasMedia[i] > 0) + return true; + } + if (hasSavedMessages) { + return true; + } + if (parentFragment != null && dialogId == parentFragment.getUserConfig().getClientUserId() && topicId == 0 && parentFragment.getMessagesController().getSavedMessagesController().hasDialogs()) { + return true; + } + // TODO: stories? + return false; + } + public SharedMediaPreloader(BaseFragment fragment) { parentFragment = fragment; if (fragment instanceof ChatActivityInterface) { @@ -691,6 +758,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else if (fragment instanceof MediaActivity) { MediaActivity mediaActivity = (MediaActivity) fragment; dialogId = mediaActivity.getDialogId(); + } else if (fragment instanceof DialogsActivity) { + dialogId = fragment.getUserConfig().getClientUserId(); } sharedMediaData = new SharedMediaData[6]; @@ -778,7 +847,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter type = MediaDataController.MEDIA_VIDEOS_ONLY; } } - parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, 0, type, topicId,2, parentFragment.getClassGuid(), 0); + parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, 0, type, topicId,2, parentFragment.getClassGuid(), 0, null, null); lastLoadMediaCount[a] = mediaCount[a]; } } @@ -1414,6 +1483,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.savedMessagesDialogsUpdate); + profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.dialogsNeedReload); for (int a = 0; a < 10; a++) { //cellCache.add(new SharedPhotoVideoCell(context)); @@ -1440,6 +1510,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter maximumVelocity = configuration.getScaledMaximumFlingVelocity(); searching = false; + searchingReaction = null; + if (searchTagsList != null) { + searchTagsList.show(false); + } searchWas = false; pinnedHeaderShadowDrawable = context.getResources().getDrawable(R.drawable.photos_header_shadow); @@ -1470,25 +1544,59 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter searchItem.setTranslationX(parent.getMeasuredWidth() - searchItem.getRight()); } }); - searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + if (dialog_id == profileActivity.getUserConfig().getClientUserId() && profileActivity instanceof MediaActivity && canShowSearchItem()) { + searchItemIcon = menu.addItem(11, R.drawable.ic_ab_search); + } + searchItem = menu.addItem(0, 0).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchExpand() { searching = true; + if (searchTagsList != null) { + searchTagsList.show((getSelectedTab() == TAB_SAVED_DIALOGS || getSelectedTab() == TAB_SAVED_MESSAGES) && searchTagsList.hasFilters()); + } + if (photoVideoOptionsItem != null) { + photoVideoOptionsItem.setVisibility(View.GONE); + } + if (searchItemIcon != null) { + searchItemIcon.setVisibility(View.GONE); + } + searchItem.setVisibility(View.GONE); onSearchStateChanged(true); + if (optionsSearchImageView != null) { + optionsSearchImageView.animate().scaleX(0.6f).scaleY(0.6f).alpha(0).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } } @Override public void onSearchCollapse() { searching = false; + searchingReaction = null; + if (searchItemIcon != null) { + searchItemIcon.setVisibility(View.VISIBLE); + } + if (photoVideoOptionsItem != null && getPhotoVideoOptionsAlpha(0) > .5f) { + photoVideoOptionsItem.setVisibility(View.VISIBLE); + } + if (searchTagsList != null) { + searchTagsList.clear(); + searchTagsList.show(false); + } + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.clearSearch(); + } searchWas = false; + searchItem.setVisibility(View.VISIBLE); documentsSearchAdapter.search(null, true); linksSearchAdapter.search(null, true); audioSearchAdapter.search(null, true); groupUsersSearchAdapter.search(null, true); if (savedMessagesSearchAdapter != null) { - savedMessagesSearchAdapter.search(null); + savedMessagesSearchAdapter.search(null, null); } onSearchStateChanged(false); + if (optionsSearchImageView != null) { + optionsSearchImageView.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } if (ignoreSearchCollapse) { ignoreSearchCollapse = false; return; @@ -1499,11 +1607,14 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public void onTextChanged(EditText editText) { String text = editText.getText().toString(); - if (text.length() != 0) { - searchWas = true; - } else { - searchWas = false; + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.setSearchQuery(text); + if (TextUtils.isEmpty(text) && searchingReaction == null) { + savedMessagesContainer.chatActivity.clearSearch(); + } } + searchItem.setVisibility(View.GONE); + searchWas = text.length() != 0 || searchingReaction != null; switchToCurrentSelectedMode(false); if (mediaPages[0].selectedType == TAB_FILES) { if (documentsSearchAdapter == null) { @@ -1529,7 +1640,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (savedMessagesSearchAdapter == null) { return; } - savedMessagesSearchAdapter.search(text); + savedMessagesSearchAdapter.search(text, searchingReaction); + } + } + + @Override + public void onSearchPressed(EditText editText) { + super.onSearchPressed(editText); + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.hitSearch(); } } @@ -1540,7 +1659,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } }); searchItem.setTranslationY(dp(10)); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); @@ -1549,16 +1668,58 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter photoVideoOptionsItem.setTranslationY(dp(10)); photoVideoOptionsItem.setVisibility(View.INVISIBLE); - Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); - calendarDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); - photoVideoOptionsItem.setImageDrawable(calendarDrawable); - photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); +// Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); +// calendarDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); +// photoVideoOptionsItem.setImageDrawable(calendarDrawable); +// photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); if (!isArchivedOnlyStoriesView()) { actionBar.addView(photoVideoOptionsItem, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); + + optionsSearchImageView = new RLottieImageView(context); + optionsSearchImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + optionsSearchImageView.setAnimation(R.raw.options_to_search, 24, 24); + optionsSearchImageView.getAnimatedDrawable().multiplySpeed(2f); + optionsSearchImageView.getAnimatedDrawable().setPlayInDirectionOfCustomEndFrame(true); + optionsSearchImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + optionsSearchImageView.setVisibility(GONE); + actionBar.addView(optionsSearchImageView, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); } photoVideoOptionsItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { + if (getSelectedTab() == TAB_SAVED_DIALOGS) { + ItemOptions.makeOptions(profileActivity, photoVideoOptionsItem) + .add(R.drawable.msg_discussion, LocaleController.getString(R.string.SavedViewAsMessages), () -> { + profileActivity.getMessagesController().setSavedViewAs(false); + Bundle args = new Bundle(); + args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); + profileActivity.presentFragment(new ChatActivity(args), true); + }) + .addGap() + .add(R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut), () -> { + try { + profileActivity.getMediaDataController().installShortcut(profileActivity.getUserConfig().getClientUserId()); + } catch (Exception e) { + FileLog.e(e); + } + }) + .add(R.drawable.msg_delete, LocaleController.getString(R.string.DeleteAll), () -> { + TLRPC.User currentUser = profileActivity.getUserConfig().getCurrentUser(); + AlertsCreator.createClearOrDeleteDialogAlert(profileActivity, false, null, currentUser, false, true, true, (param) -> { + profileActivity.finishFragment(); + if (profileActivity instanceof NotificationCenter.NotificationCenterDelegate) { + profileActivity.getNotificationCenter().removeObserver((NotificationCenter.NotificationCenterDelegate) profileActivity, NotificationCenter.closeChats); + } + profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.closeChats); + profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, null, param); + profileActivity.getMessagesController().setSavedViewAs(false); + }, resourcesProvider); + }) + .translate(0, -dp(52)) + .setDimAlpha(0) + .show(); + return; + } View dividerView = new DividerCell(context); ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider) { @Override @@ -1834,11 +1995,18 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter channelRecommendationsAdapter = new ChannelRecommendationsAdapter(context); savedDialogsAdapter = new SavedDialogsAdapter(context); savedMessagesSearchAdapter = new SavedMessagesSearchAdapter(context); - if (!isStoriesView() && !includeSavedDialogs()) { + if (!isStoriesView() && !includeSavedDialogs() && topicId == 0) { Bundle args = new Bundle(); args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); args.putInt("chatMode", ChatActivity.MODE_SAVED); - savedMessagesContainer = new ChatActivityContainer(context, profileActivity.getParentLayout(), args); + savedMessagesContainer = new ChatActivityContainer(context, () -> profileActivity.getLayoutContainer(), profileActivity.getParentLayout(), args) { + @Override + protected void onSearchLoadingUpdate(boolean loading) { + if (searchItem != null) { + searchItem.setShowSearchProgress(loading); + } + } + }; savedMessagesContainer.chatActivity.setSavedDialog(dialog_id); savedMessagesContainer.chatActivity.reversed = true; } @@ -1909,18 +2077,18 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); if (canShowSearchItem()) { if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); + searchAlpha = 1.0f - scrollProgress; } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); + searchAlpha = scrollProgress; } + updateSearchItemIcon(scrollProgress); - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + optionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); } else { - searchItem.setAlpha(0.0f); + searchAlpha = 0; } - + updateOptionsSearch(); } } invalidateBlur(); @@ -2080,7 +2248,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (photoVideoChangeColumnsAnimation && changeColumnsTab == TAB_ARCHIVED_STORIES && mediaPage.animationSupportingListView.getChildCount() > 0) { View supportingTopChild = mediaPage.animationSupportingListView.getChildAt(0); if (supportingTopChild != null && mediaPage.animationSupportingListView.getChildAdapterPosition(supportingTopChild) == 0) { - top = AndroidUtilities.lerp(top, supportingTopChild.getTop(), photoVideoChangeColumnsProgress); + top = lerp(top, supportingTopChild.getTop(), photoVideoChangeColumnsProgress); } } if (archivedHintPaint == null) { @@ -2433,12 +2601,20 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } return super.getSelectorColor(position); } + + @Override + public void onScrolled(int dx, int dy) { + super.onScrolled(dx, dy); + if (scrollingByUser && getSelectedTab() == TAB_SAVED_DIALOGS && profileActivity != null) { + AndroidUtilities.hideKeyboard(profileActivity.getParentActivity().getCurrentFocus()); + } + } }; mediaPages[a].listView.setFastScrollEnabled(RecyclerListView.FastScroll.DATE_TYPE); mediaPages[a].listView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); mediaPages[a].listView.setPinnedSectionOffsetY(-dp(2)); - mediaPages[a].listView.setPadding(0, dp(2), 0, 0); + mediaPages[a].listView.setPadding(0, 0, 0, 0); mediaPages[a].listView.setItemAnimator(null); mediaPages[a].listView.setClipToPadding(false); mediaPages[a].listView.setSectionsType(RecyclerListView.SECTIONS_TYPE_DATE); @@ -2611,13 +2787,29 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter position -= savedMessagesSearchAdapter.dialogs.size(); if (position < savedMessagesSearchAdapter.messages.size()) { MessageObject msg = savedMessagesSearchAdapter.messages.get(position); + final int pos = position; Bundle args = new Bundle(); args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); args.putInt("message_id", msg.getId()); - args.putInt("chatMode", ChatActivity.MODE_SAVED); - ChatActivity chatActivity = new ChatActivity(args); - chatActivity.setSavedDialog(msg.getSavedDialogId()); + ChatActivity chatActivity = new ChatActivity(args) { + boolean firstCreateView = true; + @Override + public void onTransitionAnimationStart(boolean isOpen, boolean backward) { + if (firstCreateView) { + if (searchItem != null) { + openSearchWithText(""); + searchItem.setSearchFieldText(savedMessagesSearchAdapter.lastQuery, false); + } + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(savedMessagesSearchAdapter.lastReaction, false); + } + profileActivity.getMediaDataController().portSavedSearchResults(getClassGuid(), savedMessagesSearchAdapter.lastReaction, savedMessagesSearchAdapter.lastQuery, savedMessagesSearchAdapter.cachedMessages, savedMessagesSearchAdapter.loadedMessages, pos, savedMessagesSearchAdapter.count, savedMessagesSearchAdapter.endReached); + firstCreateView = false; + } + super.onTransitionAnimationStart(isOpen, backward); + } + }; chatActivity.setHighlightMessageId(msg.getId()); profileActivity.presentFragment(chatActivity); } @@ -2670,6 +2862,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (photoVideoChangeColumnsAnimation) { return false; } + if (mediaPage.listView.getAdapter() == savedMessagesSearchAdapter) { + return false; + } if (isActionModeShowed && mediaPage.selectedType != TAB_SAVED_DIALOGS) { mediaPage.listView.clickItem(view, position); return true; @@ -2824,6 +3019,50 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter }); addView(scrollSlidingTextTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + searchTagsList = new SearchTagsList(getContext(), profileActivity, null, profileActivity.getCurrentAccount(), includeSavedDialogs() ? 0 : dialog_id, resourcesProvider, false) { + @Override + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + searchingReaction = reaction; + final String text = searchItem.getSearchField().getText().toString(); + searchWas = text.length() != 0 || searchingReaction != null; + switchToCurrentSelectedMode(false); + if (mediaPages[0].selectedType == TAB_SAVED_DIALOGS) { + if (savedMessagesSearchAdapter != null) { + savedMessagesSearchAdapter.search(text, searchingReaction); + } + AndroidUtilities.hideKeyboard(searchItem.getSearchField()); + } else if (mediaPages[0].selectedType == TAB_SAVED_MESSAGES) { + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.setTagFilter(reaction); + } + } + return true; + } + + @Override + protected void onShownUpdate(boolean finish) { + scrollSlidingTextTabStrip.setAlpha(1f - shownT); + scrollSlidingTextTabStrip.setPivotX(scrollSlidingTextTabStrip.getWidth() / 2f); + scrollSlidingTextTabStrip.setScaleX(.8f + .2f * (1f - shownT)); + scrollSlidingTextTabStrip.setPivotY(dp(48)); + scrollSlidingTextTabStrip.setScaleY(.8f + .2f * (1f - shownT)); + } + + @Override + public void updateTags(boolean notify) { + super.updateTags(notify); + show(searching && (getSelectedTab() == TAB_SAVED_DIALOGS || getSelectedTab() == TAB_SAVED_MESSAGES) && searchTagsList.hasFilters()); + if (searchItemIcon != null) { + searchItemIcon.setIcon(hasFilters() && profileActivity.getUserConfig().isPremium() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search, notify); + } + if (searchItem != null) { + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); + } + } + }; + searchTagsList.setShown(0f); + searchTagsList.attach(); + addView(searchTagsList, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 0, 4, 0, 0)); addView(actionModeLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); } @@ -3096,7 +3335,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(2 + 64) : dp(2), + changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0, mediaPage.animationSupportingListView.getPaddingRight(), mediaPage.animationSupportingListView.getPaddingBottom() ); @@ -3297,7 +3536,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - dp(2) + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), mediaPage.animationSupportingListView.getPaddingRight(), mediaPage.animationSupportingListView.getPaddingBottom() ); @@ -3410,6 +3649,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter switchToCurrentSelectedMode(true); animatingForward = forward; onSelectedTabChanged(); + animateSearchToOptions(!isSearchItemVisible(id), true); + updateOptionsSearch(true); } @Override @@ -3431,19 +3672,16 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } onTabProgress(getTabProgress()); - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(progress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); - if (canShowSearchItem()) { - if (searchItemState == 1) { - searchItem.setAlpha(progress); - } else if (searchItemState == 2) { - searchItem.setAlpha(1.0f - progress); - } - } else { + optionsAlpha = getPhotoVideoOptionsAlpha(progress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0.0f; + } else { + searchAlpha = getSearchAlpha(progress); + updateSearchItemIconAnimated(); } + updateOptionsSearch(); if (progress == 1) { MediaPage tempPage = mediaPages[0]; mediaPages[0] = mediaPages[1]; @@ -3626,13 +3864,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter lastVisiblePosition = Math.max(position, lastVisiblePosition); } if (mediaPage.listView.getAdapter() == savedMessagesSearchAdapter) { - if (lastVisiblePosition + 1 >= savedMessagesSearchAdapter.dialogs.size() + savedMessagesSearchAdapter.messages.size()) { + if (lastVisiblePosition + 1 >= savedMessagesSearchAdapter.dialogs.size() + savedMessagesSearchAdapter.loadedMessages.size()) { savedMessagesSearchAdapter.loadMore(); } return; } if (lastVisiblePosition + 1 >= profileActivity.getMessagesController().getSavedMessagesController().getLoadedCount()) { - profileActivity.getMessagesController().getSavedMessagesController().loadDialogs(); + profileActivity.getMessagesController().getSavedMessagesController().loadDialogs(false); } } else if (mediaPage.selectedType != TAB_RECOMMENDED_CHANNELS && mediaPage.selectedType != TAB_SAVED_MESSAGES) { final int threshold; @@ -3666,10 +3904,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } if (!sharedMediaData[mediaPage.selectedType].endReached[0]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, null, null); } else if (mergeDialogId != 0 && !sharedMediaData[mediaPage.selectedType].endReached[1]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, null, null); } } @@ -3719,26 +3957,34 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter type = MediaDataController.MEDIA_URL; } sharedMediaData[selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, sharedMediaData[selectedType].min_id, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[selectedType].requestIndex); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, sharedMediaData[selectedType].min_id, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[selectedType].requestIndex, null, null); } public ActionBarMenuItem getSearchItem() { return searchItem; } + public RLottieImageView getSearchOptionsItem() { + return optionsSearchImageView; + } + public boolean isSearchItemVisible() { - if (mediaPages[0].selectedType == TAB_GROUPUSERS) { + return isSearchItemVisible(mediaPages[0].selectedType); + } + + public boolean isSearchItemVisible(int type) { + if (type == TAB_GROUPUSERS) { return delegate.canSearchMembers(); } return ( - mediaPages[0].selectedType != TAB_PHOTOVIDEO && - mediaPages[0].selectedType != TAB_STORIES && - mediaPages[0].selectedType != TAB_ARCHIVED_STORIES && - mediaPages[0].selectedType != TAB_VOICE && - mediaPages[0].selectedType != TAB_GIF && - mediaPages[0].selectedType != TAB_COMMON_GROUPS && - mediaPages[0].selectedType != TAB_SAVED_MESSAGES && - mediaPages[0].selectedType != TAB_RECOMMENDED_CHANNELS + type != TAB_PHOTOVIDEO && + type != TAB_STORIES && + type != TAB_ARCHIVED_STORIES && + type != TAB_VOICE && + type != TAB_GIF && + type != TAB_COMMON_GROUPS && + type != TAB_SAVED_DIALOGS && + type != TAB_RECOMMENDED_CHANNELS ); } @@ -3747,7 +3993,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } public boolean isCalendarItemVisible() { - return mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES; + return mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES || mediaPages[0].selectedType == TAB_SAVED_DIALOGS; } public int getSelectedTab() { @@ -3773,6 +4019,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (storiesAdapter.poller != null) { storiesAdapter.poller.start(pollerEnabled && getClosestTab() == TAB_STORIES); } + if (searchItem != null) { + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); + } } protected boolean canShowSearchItem() { @@ -3799,6 +4048,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.savedMessagesDialogsUpdate); + profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.dialogsNeedReload); + if (searchTagsList != null) { + searchTagsList.detach(); + } if (storiesAdapter != null && storiesAdapter.storiesList != null) { storiesAdapter.destroy(); @@ -3864,7 +4117,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter req.filter = new TLRPC.TL_inputMessagesFilterMusic(); } req.limit = 100; - req.peer = MessagesController.getInstance(profileActivity.getCurrentAccount()).getInputPeer(dialog_id); + req.peer = profileActivity.getMessagesController().getInputPeer(dialog_id); + if (topicId != 0) { + if (profileActivity.getUserConfig().getClientUserId() == dialog_id) { + req.flags |= 4; + req.saved_peer_id = profileActivity.getMessagesController().getInputPeer(topicId); + } + } int reqIndex = sharedMediaData[type].requestIndex; int reqId = ConnectionsManager.getInstance(profileActivity.getCurrentAccount()).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> @@ -3960,9 +4219,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter selectedDialogs.add(did); } } + boolean firstDialogSelf = false; String firstDialog = ""; if (!selectedDialogs.isEmpty()) { long did = selectedDialogs.get(0); + firstDialogSelf = did == profileActivity.getUserConfig().getClientUserId(); if (did < 0) { TLRPC.Chat chat = profileActivity.getMessagesController().getChat(-did); if (chat != null) { @@ -3980,8 +4241,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } AlertDialog dialog = new AlertDialog.Builder(getContext(), resourcesProvider) - .setTitle(selectedDialogs.size() == 1 ? LocaleController.formatString(R.string.ClearHistoryTitleSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryTitleMultiple", selectedDialogs.size())) - .setMessage(selectedDialogs.size() == 1 ? LocaleController.formatString(R.string.ClearHistoryMessageSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryMessageMultiple", selectedDialogs.size())) + .setTitle(selectedDialogs.size() == 1 ? LocaleController.formatString(firstDialogSelf ? R.string.ClearHistoryMyNotesTitle : R.string.ClearHistoryTitleSingle2, firstDialog) : LocaleController.formatPluralString("ClearHistoryTitleMultiple", selectedDialogs.size())) + .setMessage(selectedDialogs.size() == 1 ? LocaleController.formatString(firstDialogSelf ? R.string.ClearHistoryMyNotesMessage : R.string.ClearHistoryMessageSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryMessageMultiple", selectedDialogs.size())) .setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { for (int i = 0; i < selectedDialogs.size(); ++i) { final long did = selectedDialogs.get(i); @@ -4144,7 +4405,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter selectedDialogs.add(did); } } - if (!controller.updatePinned(selectedDialogs, id == pin)) { + if (!controller.updatePinned(selectedDialogs, id == pin, true)) { LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); profileActivity.showDialog(limitReachedBottomSheet); } else { @@ -4164,20 +4425,14 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (id < 0) { return false; } - if (canShowSearchItem()) { - if (searchItemState != 0) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - } - searchItemState = 0; - } - } else { + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; + } else { + searchAlpha = getSearchAlpha(0); + updateSearchItemIcon(0); } + updateOptionsSearch(); getParent().requestDisallowInterceptTouchEvent(true); hideFloatingDateView(true); @@ -4340,19 +4595,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[1].setTranslationX(dx - mediaPages[0].getMeasuredWidth()); } float scrollProgress = Math.abs(dx) / (float) mediaPages[0].getMeasuredWidth(); - if (canShowSearchItem()) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); - } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); - } - - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + if (!canShowSearchItem()) { + searchAlpha = 0; } else { - searchItem.setAlpha(0.0f); + searchAlpha = getSearchAlpha(scrollProgress); + updateSearchItemIcon(scrollProgress); + optionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); } + updateOptionsSearch(); scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); onTabProgress(getTabProgress()); onSelectedTabChanged(); @@ -4452,17 +4703,14 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter tabsAnimation = null; if (backAnimation) { mediaPages[1].setVisibility(View.GONE); - if (canShowSearchItem()) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - } - } else { + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; + } else { + searchAlpha = getSearchAlpha(0); + updateSearchItemIcon(0); } + updateOptionsSearch(); searchItemState = 0; } else { MediaPage tempPage = mediaPages[0]; @@ -4669,7 +4917,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } if (!fromStart && loadIndex == 0 && sharedMediaData[type].endReached[loadIndex] && mergeDialogId != 0) { sharedMediaData[type].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[type].requestIndex); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[type].requestIndex, null, null); } if (adapter != null) { RecyclerListView listView = null; @@ -4956,6 +5204,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter checkCurrentTabValid(); onSelectedTabChanged(); } + } else if (id == NotificationCenter.dialogsNeedReload) { + savedDialogsAdapter.update(true); } } @@ -5301,7 +5551,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (hasRecommendations != scrollSlidingTextTabStrip.hasTab(TAB_RECOMMENDED_CHANNELS)) { changed++; } - hasSavedDialogs = includeSavedDialogs() && !profileActivity.getMessagesController().getSavedMessagesController().unsupported && profileActivity.getMessagesController().getSavedMessagesController().getAllCount() > 0; + hasSavedDialogs = includeSavedDialogs() && !profileActivity.getMessagesController().getSavedMessagesController().unsupported && profileActivity.getMessagesController().getSavedMessagesController().hasDialogs(); if (hasSavedDialogs != scrollSlidingTextTabStrip.hasTab(TAB_SAVED_DIALOGS)) { changed++; } @@ -5386,6 +5636,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } } + if (hasSavedMessages) { + if (!scrollSlidingTextTabStrip.hasTab(TAB_SAVED_MESSAGES)) { + scrollSlidingTextTabStrip.addTextTab(TAB_SAVED_MESSAGES, LocaleController.getString(R.string.SavedMessagesTab2), idToView); + } + MessagesController.getGlobalMainSettings().edit().putInt("savedhint", 3).apply(); + } if (hasMedia[1] > 0) { if (!scrollSlidingTextTabStrip.hasTab(TAB_FILES)) { scrollSlidingTextTabStrip.addTextTab(TAB_FILES, LocaleController.getString("SharedFilesTab2", R.string.SharedFilesTab2), idToView); @@ -5429,12 +5685,6 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter scrollSlidingTextTabStrip.addTextTab(TAB_RECOMMENDED_CHANNELS, LocaleController.getString(R.string.SimilarChannelsTab), idToView); } } - if (hasSavedMessages) { - if (!scrollSlidingTextTabStrip.hasTab(TAB_SAVED_MESSAGES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_SAVED_MESSAGES, LocaleController.getString(R.string.SavedMessagesTab), idToView); - } - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", 3).apply(); - } } } int id = scrollSlidingTextTabStrip.getCurrentTabId(); @@ -5484,6 +5734,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (animated) { if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers()) { searching = false; + if (searchTagsList != null) { + searchTagsList.show(false); + } searchWas = false; switchToCurrentSelectedMode(true); return; @@ -5523,7 +5776,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } else if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { if (savedMessagesSearchAdapter != null) { - savedMessagesSearchAdapter.search(text); + savedMessagesSearchAdapter.search(text, searchingReaction); if (currentAdapter != savedMessagesSearchAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(savedMessagesSearchAdapter); @@ -5574,7 +5827,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); mediaPages[a].listView.setPadding( mediaPages[a].listView.getPaddingLeft(), - dp(2) + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), mediaPages[a].listView.getPaddingRight(), mediaPages[a].listView.getPaddingBottom() ); @@ -5683,14 +5936,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } if (savedMessagesContainer != null && mediaPages[a].selectedType != TAB_SAVED_MESSAGES && savedMessagesContainer.getParent() == mediaPages[a]) { + savedMessagesContainer.chatActivity.onRemoveFromParent(); mediaPages[a].removeView(savedMessagesContainer); } - if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_STORIES || mediaPages[a].selectedType == TAB_ARCHIVED_STORIES || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers() || mediaPages[a].selectedType == TAB_RECOMMENDED_CHANNELS || mediaPages[a].selectedType == TAB_SAVED_MESSAGES) { + if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_SAVED_DIALOGS || mediaPages[a].selectedType == TAB_STORIES || mediaPages[a].selectedType == TAB_ARCHIVED_STORIES || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers() || mediaPages[a].selectedType == TAB_RECOMMENDED_CHANNELS) { if (animated) { searchItemState = 2; } else { searchItemState = 0; - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); + searchItem.setVisibility(isStoriesView() || searching ? View.GONE : View.INVISIBLE); } } else { if (animated) { @@ -5701,20 +5955,23 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); } - searchItem.setAlpha(0.0f); + searchAlpha = getSearchAlpha(a); + updateSearchItemIcon(1f - a); } else { searchItemState = 0; + searchAlpha = 1f; } } else if (searchItem.getVisibility() == View.INVISIBLE) { if (canShowSearchItem()) { searchItemState = 0; - searchItem.setAlpha(1.0f); + searchAlpha = 1; searchItem.setVisibility(View.VISIBLE); } else { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; } } + updateOptionsSearch(); } if (mediaPages[a].selectedType == TAB_COMMON_GROUPS) { if (!commonGroupsAdapter.loading && !commonGroupsAdapter.endReached && commonGroupsAdapter.chats.isEmpty()) { @@ -5750,7 +6007,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter type = MediaDataController.MEDIA_VIDEOS_ONLY; } } - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPages[a].selectedType].requestIndex); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPages[a].selectedType].requestIndex, null, null); } } if (mediaPages[a].selectedType == TAB_STORIES) { @@ -5781,8 +6038,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter ignoreSearchCollapse = true; actionBar.closeSearchField(); searchItemState = 0; - searchItem.setAlpha(0.0f); + searchAlpha = 0; searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); + updateOptionsSearch(); } } @@ -6852,7 +7110,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter currentType = type; } - public void queryServerSearch(final String query, final int max_id, long did) { + public void queryServerSearch(final String query, final int max_id, long did, long topicId) { if (DialogObject.isEncryptedDialog(did)) { return; } @@ -6879,6 +7137,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } req.q = query; req.peer = profileActivity.getMessagesController().getInputPeer(did); + if (topicId != 0) { + if (did == profileActivity.getUserConfig().getClientUserId()) { + req.flags |= 4; + req.saved_peer_id = profileActivity.getMessagesController().getInputPeer(topicId); + } else { + req.flags |= 2; + req.top_msg_id = (int) topicId; + } + } if (req.peer == null) { return; } @@ -6960,9 +7227,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter AndroidUtilities.runOnUIThread(searchRunnable = () -> { if (!sharedMediaData[currentType].messages.isEmpty() && (currentType == 1 || currentType == 4)) { MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); - queryServerSearch(query, messageObject.getId(), messageObject.getDialogId()); + queryServerSearch(query, messageObject.getId(), messageObject.getDialogId(), dialog_id == profileActivity.getUserConfig().getClientUserId() ? messageObject.getSavedDialogId() : 0); } else if (currentType == 3) { - queryServerSearch(query, 0, dialog_id); + queryServerSearch(query, 0, dialog_id, topicId); } if (currentType == 1 || currentType == 4) { final ArrayList copy = new ArrayList<>(sharedMediaData[currentType].messages); @@ -7281,7 +7548,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { - if (!isActionModeShowed) { + if (!isActionModeShowed || recyclerView.getAdapter() == savedMessagesSearchAdapter) { return makeMovementFlags(0, 0); } SavedMessagesController.SavedDialog d = getDialog(viewHolder); @@ -7316,7 +7583,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder sourceHolder, @NonNull RecyclerView.ViewHolder targetHolder) { - if (!isActionModeShowed) { + if (!isActionModeShowed || recyclerView.getAdapter() == savedMessagesSearchAdapter) { return false; } SavedMessagesController.SavedDialog source = getDialog(sourceHolder); @@ -7349,7 +7616,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mContext = context; controller = profileActivity.getMessagesController().getSavedMessagesController(); if (includeSavedDialogs()) { - controller.loadDialogs(); + controller.loadDialogs(false); } setHasStableIds(true); update(false); @@ -7436,7 +7703,6 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { DialogCell cell = new DialogCell(null, mContext, false, true) { - @Override public boolean isForumCell() { return false; @@ -7464,6 +7730,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter DialogCell cell = (DialogCell) holder.itemView; SavedMessagesController.SavedDialog d = dialogs.get(position); cell.setDialog(d.dialogId, d.message, d.getDate(), false, false); + cell.isSavedDialogCell = true; cell.setChecked(selectedDialogs.contains(d.dialogId), false); cell.useSeparator = position + 1 < getItemCount(); } @@ -7489,6 +7756,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private final int currentAccount; public final ArrayList dialogs = new ArrayList<>(); public final ArrayList messages = new ArrayList<>(); + public final ArrayList loadedMessages = new ArrayList<>(); + public final ArrayList cachedMessages = new ArrayList<>(); public SavedMessagesSearchAdapter(Context context) { mContext = context; currentAccount = profileActivity.getCurrentAccount(); @@ -7501,43 +7770,54 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private int count = 0; private String lastQuery; + private ReactionsLayoutInBubble.VisibleReaction lastReaction; private int reqId = -1; - public void search(String query) { - if (TextUtils.equals(query, lastQuery)) { + + public void search(String query, ReactionsLayoutInBubble.VisibleReaction reaction) { + if (TextUtils.equals(query, lastQuery) && (lastReaction == null && reaction == null || lastReaction != null && lastReaction.equals(reaction))) { return; } lastQuery = query; + lastReaction = reaction; if (reqId >= 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); reqId = -1; } + cachedMessages.clear(); + loadedMessages.clear(); messages.clear(); count = 0; endReached = false; loading = true; dialogs.clear(); - dialogs.addAll(MessagesController.getInstance(currentAccount).getSavedMessagesController().searchDialogs(query)); + if (lastReaction == null) { + dialogs.addAll(MessagesController.getInstance(currentAccount).getSavedMessagesController().searchDialogs(query)); + } for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { mediaPages[a].emptyView.showProgress(true, true); } } - notifyDataSetChanged(); + if (lastReaction == null) { + notifyDataSetChanged(); + } AndroidUtilities.cancelRunOnUIThread(searchRunnable); - AndroidUtilities.runOnUIThread(searchRunnable, 600); + AndroidUtilities.runOnUIThread(searchRunnable, lastReaction != null ? 60 : 600); } public void loadMore() { if (endReached || loading) return; + loading = true; sendRequest(); } + int lastSearchId; private Runnable searchRunnable = this::sendRequest; private void sendRequest() { - if (TextUtils.isEmpty(lastQuery)) { + if (TextUtils.isEmpty(lastQuery) && lastReaction == null) { loading = false; return; } @@ -7545,46 +7825,98 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter req.peer = MessagesController.getInstance(currentAccount).getInputPeer(UserConfig.getInstance(currentAccount).getClientUserId()); req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); req.q = lastQuery; - if (messages.size() > 0) { - MessageObject lastMessage = messages.get(messages.size() - 1); + if (lastReaction != null) { + req.flags |= 8; + req.saved_reaction.add(lastReaction.toTLReaction()); + } + if (loadedMessages.size() > 0) { + MessageObject lastMessage = loadedMessages.get(loadedMessages.size() - 1); req.offset_id = lastMessage.getId(); } req.limit = 10; endReached = false; - reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - if (!(res instanceof TLRPC.messages_Messages)) { - return; - } - TLRPC.messages_Messages r = (TLRPC.messages_Messages) res; - MessagesController.getInstance(currentAccount).putUsers(r.users, false); - MessagesController.getInstance(currentAccount).putChats(r.chats, false); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(r.users, r.chats, true, true); - for (int i = 0; i < r.messages.size(); ++i) { - TLRPC.Message msg = r.messages.get(i); - messages.add(new MessageObject(currentAccount, msg, false, false)); - } - if (r instanceof TLRPC.TL_messages_messagesSlice) { + final int searchId = ++lastSearchId; + Runnable request = () -> { + if (searchId != lastSearchId) return; + reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (!(res instanceof TLRPC.messages_Messages) || searchId != lastSearchId) { + return; + } + TLRPC.messages_Messages r = (TLRPC.messages_Messages) res; + MessagesController.getInstance(currentAccount).putUsers(r.users, false); + MessagesController.getInstance(currentAccount).putChats(r.chats, false); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(r.users, r.chats, true, true); + for (int i = 0; i < r.messages.size(); ++i) { + TLRPC.Message msg = r.messages.get(i); + MessageObject messageObject = new MessageObject(currentAccount, msg, false, true); + if (messageObject.hasValidGroupId()) { + messageObject.isPrimaryGroupMessage = true; + } + messageObject.setQuery(lastQuery); + loadedMessages.add(messageObject); + } count = r.count; - endReached = messages.size() >= count; - } else if (r instanceof TLRPC.TL_messages_messages) { - count = messages.size(); - endReached = true; - } + if (r instanceof TLRPC.TL_messages_messagesSlice) { + endReached = loadedMessages.size() >= r.count; + } else if (r instanceof TLRPC.TL_messages_messages) { + endReached = true; + } + updateMessages(false); + loading = false; + reqId = -1; + })); + }; + if (lastReaction != null) { + MessagesStorage.getInstance(currentAccount).searchSavedByTag(lastReaction.toTLReaction(), 0, lastQuery, 100, cachedMessages.size(), (messages, users, chats, emoji) -> { + MessagesController.getInstance(currentAccount).putUsers(users, true); + MessagesController.getInstance(currentAccount).putChats(chats, true); + AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).processDocuments(emoji); + for (int i = 0; i < messages.size(); ++i) { + MessageObject messageObject = messages.get(i); + if (messageObject.hasValidGroupId() && messageObject.messageOwner.reactions != null) { + messageObject.isPrimaryGroupMessage = true; + } + messageObject.setQuery(lastQuery); + cachedMessages.add(messageObject); + } + updateMessages(true); + AndroidUtilities.runOnUIThread(request, 540); + }, false); + } else { + request.run(); + } + } + private void updateMessages(boolean fromCache) { + messages.clear(); + HashSet msgIds = new HashSet<>(); + for (int i = 0; i < loadedMessages.size(); ++i) { + MessageObject msg = loadedMessages.get(i); + if (msg != null && !msgIds.contains(msg.getId())) { + msgIds.add(msg.getId()); + messages.add(msg); + } + } + for (int i = 0; i < cachedMessages.size(); ++i) { + MessageObject msg = cachedMessages.get(i); + if (msg != null && !msgIds.contains(msg.getId())) { + msgIds.add(msg.getId()); + messages.add(msg); + } + } + + if (!fromCache || !cachedMessages.isEmpty()) { for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { - if (count == 0 && dialogs.isEmpty()) { - mediaPages[a].emptyView.title.setText(LocaleController.formatString("NoResultFoundFor", R.string.NoResultFoundFor, lastQuery)); + if (messages.isEmpty() && dialogs.isEmpty()) { + mediaPages[a].emptyView.title.setText(lastReaction != null && TextUtils.isEmpty(lastQuery) ? AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.NoResultFoundForTag), lastReaction.toCharSequence(mediaPages[a].emptyView.title.getPaint().getFontMetricsInt())) : LocaleController.formatString(R.string.NoResultFoundFor, lastQuery)); mediaPages[a].emptyView.showProgress(false, true); } } } - oldItemCounts = count; - reqId = -1; - - notifyDataSetChanged(); - loading = false; - })); + } + oldItemCounts = count; + notifyDataSetChanged(); } @Override @@ -8871,4 +9203,36 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter clip[1] = getMeasuredHeight() - getPaddingBottom(); } } + + private void updateOptionsSearch() { + updateOptionsSearch(false); + } + private void updateOptionsSearch(boolean finish) { + if (optionsSearchImageView == null) return; + optionsSearchImageView.setAlpha(searching ? 0f : Utilities.clamp(searchAlpha + optionsAlpha, 1, 0)); + if (finish) { + animateSearchToOptions(getPhotoVideoOptionsAlpha(1) > 0.5f, true); + } else if (searchItemState == 2) { + animateSearchToOptions(optionsAlpha > 0.1f, true); + } else { + animateSearchToOptions(searchAlpha < 0.1f, true); + } + } + private boolean animatingToOptions; + public void animateSearchToOptions(boolean toOptions, boolean animated) { + if (optionsSearchImageView == null) return; + if (animatingToOptions != toOptions) { + animatingToOptions = toOptions; + if (!animatingToOptions && optionsSearchImageView.getAnimatedDrawable().getCurrentFrame() < 20) { + optionsSearchImageView.getAnimatedDrawable().setCustomEndFrame(0); + } else { + optionsSearchImageView.getAnimatedDrawable().setCustomEndFrame(animatingToOptions ? 50 : 100); + } + if (animated) { + optionsSearchImageView.getAnimatedDrawable().start(); + } else { + optionsSearchImageView.getAnimatedDrawable().setCurrentFrame(optionsSearchImageView.getAnimatedDrawable().getCustomEndFrame()); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java index e4a3553d9..481078ecd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java @@ -30,6 +30,7 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.spoilers.SpoilersTextView; import org.telegram.ui.LaunchActivity; public class StickerEmptyView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -43,7 +44,7 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter. public LinearLayout linearLayout; public BackupImageView stickerView; private RadialProgressView progressBar; - public final TextView title; + public final SpoilersTextView title; public final LinkSpanDrawable.LinksTextView subtitle; private boolean progressShowing; private final Theme.ResourcesProvider resourcesProvider; @@ -103,9 +104,9 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter. stickerView = new BackupImageView(context); stickerView.setOnClickListener(view -> stickerView.getImageReceiver().startAnimation()); - title = new TextView(context); + title = new SpoilersTextView(context); - title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); title.setTag(Theme.key_windowBackgroundWhiteBlackText); title.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index 4fea03c39..070bf2ec7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -35,6 +35,7 @@ import android.text.TextWatcher; import android.transition.Transition; import android.transition.TransitionManager; import android.transition.TransitionValues; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java index a9a9afa9c..40f9827ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java @@ -179,6 +179,9 @@ public class ThanosEffect extends TextureView { } public void kill() { + if (destroyed) { + return; + } destroyed = true; for (ToSet set : toSet) { if (set.doneCallback != null) { @@ -366,27 +369,31 @@ public class ThanosEffect extends TextureView { } private void resizeInternal(int width, int height) { - if (!alive) return; + if (!alive) { + return; + } this.width = width; this.height = height; GLES31.glViewport(0, 0, width, height); GLES31.glUniform2f(sizeHandle, width, height); } - private boolean killed; public void kill() { - if (killed) return; + if (!alive) { + return; + } try { Handler handler = getHandler(); if (handler != null) { handler.sendMessage(handler.obtainMessage(DO_KILL)); } - killed = true; } catch (Exception e) {} } private void killInternal() { - if (!alive) return; + if (!alive) { + return; + } alive = false; for (int i = 0; i < pendingAnimations.size(); ++i) { Animation animation = pendingAnimations.get(i); @@ -615,36 +622,49 @@ public class ThanosEffect extends TextureView { } }; - public void layoutAnimations() { - - } - private final ArrayList toAddAnimations = new ArrayList<>(); public void animateGroup(ArrayList views, Runnable whenDone) { - if (!alive) return; - Animation animation = new Animation(views, whenDone); - Handler handler = getHandler(); - running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); + if (!alive) { + for (int i = 0; i < views.size(); ++i) { + views.get(i).setVisibility(GONE); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; } + Animation animation = new Animation(views, whenDone); + running = true; + postRunnable(() -> addAnimationInternal(animation)); } public void animate(View view, float durationMultipier, Runnable whenDone) { - if (!alive) return; + if (!alive) { + if (view != null) { + view.setVisibility(GONE); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; + } Animation animation = new Animation(view, durationMultipier, whenDone); Handler handler = getHandler(); running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); - } + postRunnable(() -> addAnimationInternal(animation)); } public void cancel(View view) { - if (!alive) return; + if (!alive) { + return; + } Handler handler = getHandler(); if (handler == null) { for (int i = 0; i < toAddAnimations.size(); ++i) { @@ -672,15 +692,25 @@ public class ThanosEffect extends TextureView { } public void animate(Matrix matrix, Bitmap bitmap, Runnable whenStart, Runnable whenDone) { - if (!alive) return; + if (!alive) { + AndroidUtilities.runOnUIThread(() -> { + if (whenStart != null) { + whenStart.run(); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + }); + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; + } Animation animation = new Animation(matrix, bitmap, whenStart, whenDone); Handler handler = getHandler(); running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); - } + postRunnable(() -> addAnimationInternal(animation)); } private void cancelAnimationInternal(View view) { @@ -823,7 +853,7 @@ public class ThanosEffect extends TextureView { } MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); - MessageObject.GroupedMessagePosition position = group == null || group.positions == null ? null : group.positions.get(cell.getMessageObject()); + MessageObject.GroupedMessagePosition position = group == null || group.positions == null ? null : group.getPosition(cell.getMessageObject()); if (k == 0) { if (position != null || cell.getTransitionParams().animateBackgroundBoundsInner) { if (position == null || (position.last || position.minX == 0 && position.minY == 0)) { @@ -922,6 +952,8 @@ public class ThanosEffect extends TextureView { t -= top; b -= top; + l -= left; + r -= left; boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; if (useScale) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java index 0e79b4ff1..8ffbdc205 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java @@ -2,13 +2,16 @@ package org.telegram.ui.Components.spoilers; import android.content.Context; import android.graphics.Canvas; +import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region; import android.text.Layout; +import android.text.Spannable; import android.text.Spanned; import android.text.StaticLayout; import android.view.MotionEvent; @@ -16,6 +19,8 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.Cells.TextSelectionHelper; +import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.AnimatedEmojiSpan; import java.util.ArrayList; import java.util.List; @@ -30,6 +35,9 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si private Paint xRefPaint; public boolean allowClickSpoilers = true; + public int cacheType = AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + private AnimatedEmojiSpan.EmojiGroupedSpans animatedEmoji; + public SpoilersTextView(Context context) { this(context, true); } @@ -68,6 +76,7 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); invalidateSpoilers(); + updateAnimatedEmoji(true); } @Override @@ -76,6 +85,13 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si invalidateSpoilers(); } + private ColorFilter animatedEmojiColorFilter; + @Override + public void setTextColor(int color) { + super.setTextColor(color); + animatedEmojiColorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); + } + @Override protected void onDraw(Canvas canvas) { int pl = getPaddingLeft(), pt = getPaddingTop(); @@ -100,6 +116,14 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si super.onDraw(canvas); canvas.restore(); + updateAnimatedEmoji(false); + if (animatedEmoji != null) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), animatedEmoji, 0, spoilers, 0, getHeight(), 0, 1f, animatedEmojiColorFilter); + canvas.restore(); + } + if (!spoilers.isEmpty()) { boolean useAlphaLayer = spoilers.get(0).getRippleProgress() != -1; if (useAlphaLayer) { @@ -127,12 +151,29 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si } } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateAnimatedEmoji(true); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); invalidateSpoilers(); } + private Layout lastLayout = null; + private int lastTextLength; + public void updateAnimatedEmoji(boolean force) { + int newTextLength = (getLayout() == null || getLayout().getText() == null) ? 0 : getLayout().getText().length(); + if (force || lastLayout != getLayout() || lastTextLength != newTextLength) { + animatedEmoji = AnimatedEmojiSpan.update(cacheType, this, animatedEmoji, getLayout()); + lastLayout = getLayout(); + lastTextLength = newTextLength; + } + } + private void invalidateSpoilers() { if (spoilers == null) return; // Check for a super constructor spoilersPool.addAll(spoilers); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 1e379bf1d..6691b5e75 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -401,6 +401,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private boolean askingForPermissions; private RLottieDrawable passcodeDrawable; private SearchViewPager searchViewPager; + private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader; public DialogStoriesCell dialogStoriesCell; public boolean dialogStoriesCellVisible; public float progressToDialogStoriesCell; @@ -2718,6 +2719,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getContactsController().loadGlobalPrivacySetting(); + if (getMessagesController().savedViewAsChats) { + getMessagesController().getSavedMessagesController().preloadDialogs(true); + } + return true; } @@ -4979,6 +4984,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. animateToHasStories = false; hasOnlySlefStories = false; hasStories = false; + + if (onlySelect && initialDialogsType == DIALOGS_TYPE_FORWARD) { + MessagesController.getInstance(currentAccount).getSavedReactionTags(0); + } + if (!onlySelect || initialDialogsType == DIALOGS_TYPE_FORWARD) { final FrameLayout.LayoutParams layoutParams = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT); if (inPreviewMode && Build.VERSION.SDK_INT >= 21) { @@ -6055,7 +6065,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. totalOffset -= dialogsHintCell.getMeasuredHeight() * rightSlidingDialogContainer.openedProgress; } dialogsHintCell.setTranslationY(totalOffset); - totalOffset += dialogsHintCell.getMeasuredHeight(); + totalOffset += dialogsHintCell.getMeasuredHeight() * (1f - searchAnimationProgress); } if (authHintCell != null && authHintCell.getVisibility() == View.VISIBLE) { if (rightSlidingDialogContainer != null && rightSlidingDialogContainer.hasFragment()) { @@ -7243,9 +7253,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } } + if (fragmentContextView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fragmentContextView.setTranslationZ(1f); + } searchAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + if (fragmentContextView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fragmentContextView.setTranslationZ(0f); + } notificationsLocker.unlock(); if (searchAnimator != animation) { return; @@ -7829,7 +7845,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (searchViewPager.actionModeShowing()) { searchViewPager.hideActionMode(); } - if (searchString != null) { + if (dialogId == getUserConfig().getClientUserId() && getMessagesController().savedViewAsChats) { + args = new Bundle(); + args.putLong("dialog_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putInt("type", MediaActivity.TYPE_MEDIA); + args.putInt("start_from", SharedMediaLayout.TAB_SAVED_DIALOGS); + if (sharedMediaPreloader == null) { + sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(this); + } + MediaActivity mediaActivity = new MediaActivity(args, sharedMediaPreloader); + presentFragment(mediaActivity); + } else if (searchString != null) { if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { getNotificationCenter().postNotificationName(NotificationCenter.closeChats); presentFragment(new ChatActivity(args)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index c8bb51767..89ca3e1c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -316,7 +316,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } if (!TextUtils.isEmpty(txt)) { editText.setText(txt); - editText.setSelection(editText.getText().length()); + editText.setSelection(0, editText.getText().length()); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java index 002829475..09788178e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java @@ -75,7 +75,7 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC private boolean removeStickerSet; private TLRPC.ChatFull info; - private long chatId; + private final long chatId; private int infoRow; private int headerRow; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 607442316..739c51209 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -48,6 +48,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ClickableSpan; import android.util.Base64; +import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.view.ActionMode; @@ -171,6 +172,7 @@ import org.telegram.ui.Components.Premium.boosts.UserSelectorBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SearchTagsList; import org.telegram.ui.Components.SharingLocationsAlert; import org.telegram.ui.Components.SideMenultItemAnimator; import org.telegram.ui.Components.SizeNotifierFrameLayout; @@ -1312,6 +1314,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati return frameLayout; } + private boolean switchingAccount; public void switchToAccount(int account, boolean removeAll) { switchToAccount(account, removeAll, obj -> new DialogsActivity(null)); } @@ -1320,6 +1323,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (account == UserConfig.selectedAccount || !UserConfig.isValidAccount(account)) { return; } + switchingAccount = true; ConnectionsManager.getInstance(currentAccount).setAppPaused(true, false); UserConfig.selectedAccount = account; @@ -1359,6 +1363,8 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati showTosActivity(account, UserConfig.getInstance(account).unacceptedTermsOfService); } updateCurrentConnectionState(currentAccount); + + switchingAccount = false; } private void switchToAvailableAccountOrLogout() { @@ -1696,7 +1702,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati long push_chat_id = 0; long[] push_story_dids = null; int push_story_id = 0; - int push_topic_id = 0; + long push_topic_id = 0; int push_enc_id = 0; int push_msg_id = 0; int open_settings = 0; @@ -2580,7 +2586,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati data = Uri.parse(url); theme = data.getQueryParameter("slug"); } else if (url.startsWith("tg:settings") || url.startsWith("tg://settings")) { - if (url.contains("themes")) { + if (url.contains("themes") || url.contains("theme")) { open_settings = 2; } else if (url.contains("devices")) { open_settings = 3; @@ -2588,6 +2594,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati open_settings = 4; } else if (url.contains("change_number")) { open_settings = 5; + } else if (url.contains("language")) { + open_settings = 10; + } else if (url.contains("auto_delete")) { + open_settings = 11; + } else if (url.contains("privacy")) { + open_settings = 12; } else if (url.contains("?enablelogs")) { open_settings = 7; } else if (url.contains("?sendlogs")) { @@ -2759,7 +2771,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati long userId = intent.getLongExtra("userId", 0); int encId = intent.getIntExtra("encId", 0); int widgetId = intent.getIntExtra("appWidgetId", 0); - int topicId = intent.getIntExtra("topicId", 0); + long topicId = intent.getLongExtra("topicId", 0); if (widgetId != 0) { open_settings = 6; open_widget_edit = widgetId; @@ -2857,7 +2869,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { boolean finalIsNew = isNew; long finalPush_chat_id = push_chat_id; - int finalPush_topic_id = push_topic_id; + long finalPush_topic_id = push_topic_id; MessagesController.getInstance(currentAccount).getTopicsController().loadTopic(push_chat_id, push_topic_id, () -> { TLRPC.TL_forumTopic loadedTopic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(finalPush_chat_id, finalPush_topic_id); FileLog.d("LaunchActivity openForum after load " + finalPush_chat_id + " " + finalPush_topic_id + " TL_forumTopic " + loadedTopic); @@ -2978,6 +2990,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati closePrevious = true; } else if (open_settings == 6) { fragment = new EditWidgetActivity(open_widget_edit_type, open_widget_edit); + } else if (open_settings == 10) { + fragment = new LanguageSelectActivity(); + } else if (open_settings == 11) { + fragment = new AutoDeleteMessagesActivity(); + } else if (open_settings == 12) { + fragment = new PrivacySettingsActivity(); } else { fragment = null; } @@ -5223,7 +5241,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati return foundContacts; } - public void checkAppUpdate(boolean force) { + public void checkAppUpdate(boolean force, Browser.Progress progress) { if (!force && BuildVars.DEBUG_VERSION || !force && !BuildVars.CHECK_UPDATES) { return; } @@ -5240,7 +5258,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati req.source = ""; } final int accountNum = currentAccount; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { SharedConfig.lastUpdateCheckTime = System.currentTimeMillis(); SharedConfig.saveConfig(); if (response instanceof TLRPC.TL_help_appUpdate) { @@ -5249,7 +5267,8 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (SharedConfig.pendingAppUpdate != null && SharedConfig.pendingAppUpdate.version.equals(res.version)) { return; } - if (SharedConfig.setNewAppVersionAvailable(res)) { + final boolean newVersionAvailable = SharedConfig.setNewAppVersionAvailable(res); + if (newVersionAvailable) { if (res.can_not_skip) { showUpdateActivity(accountNum, res, false); } else if (ApplicationLoader.isStandaloneBuild() || BuildVars.DEBUG_VERSION) { @@ -5258,9 +5277,42 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable); } + if (progress != null) { + progress.end(); + if (!newVersionAvailable) { + BaseFragment fragment = getLastFragment(); + if (fragment != null) { + BulletinFactory.of(fragment).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString(R.string.YourVersionIsLatest)).show(); + } + } + } + }); + } else if (response instanceof TLRPC.TL_help_noAppUpdate) { + AndroidUtilities.runOnUIThread(() -> { + if (progress != null) { + progress.end(); + BaseFragment fragment = getLastFragment(); + if (fragment != null) { + BulletinFactory.of(fragment).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString(R.string.YourVersionIsLatest)).show(); + } + } + }); + } else if (error != null) { + AndroidUtilities.runOnUIThread(() -> { + if (progress != null) { + progress.end(); + BaseFragment fragment = getLastFragment(); + if (fragment != null) { + BulletinFactory.of(fragment).showForError(error); + } + } }); } }); + if (progress != null) { + progress.init(); + progress.onCancel(() -> ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true)); + } } public Dialog showAlertDialog(AlertDialog.Builder builder) { @@ -5981,7 +6033,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else if (SharedConfig.pendingAppUpdate != null && SharedConfig.pendingAppUpdate.can_not_skip) { showUpdateActivity(UserConfig.selectedAccount, SharedConfig.pendingAppUpdate, true); } - checkAppUpdate(false); + checkAppUpdate(false, null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ApplicationLoader.canDrawOverlays = Settings.canDrawOverlays(this); @@ -7175,9 +7227,11 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati finish(); return; } - if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { + if (SearchTagsList.onBackPressedRenameTagAlert()) { + return; + } else if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { ContentPreviewViewer.getInstance().closeWithMenu(); - } if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { + } else if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { SecretMediaViewer.getInstance().closePhoto(true, false); } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { PhotoViewer.getInstance().closePhoto(true, false); @@ -7406,7 +7460,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } return result; } else if (!tabletFullSize && layout != rightActionBarLayout) { - rightActionBarLayout.getView().setVisibility(View.VISIBLE); + if (rightActionBarLayout.getView() != null) { + rightActionBarLayout.getView().setVisibility(View.VISIBLE); + } backgroundTablet.setVisibility(View.GONE); rightActionBarLayout.removeAllFragments(); rightActionBarLayout.presentFragment(params.setNoAnimation(true).setRemoveLast(removeLast).setCheckPresentFromDelegate(false)); @@ -7563,7 +7619,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati @Override public boolean needCloseLastFragment(INavigationLayout layout) { if (AndroidUtilities.isTablet()) { - if (layout == actionBarLayout && layout.getFragmentStack().size() <= 1) { + if (layout == actionBarLayout && layout.getFragmentStack().size() <= 1 && !switchingAccount) { onFinish(); finish(); return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index ccc48d02b..335c555ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -4164,7 +4164,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private void setDonePressed(boolean value) { donePressed = value; swipeBackEnabled = !value; - if (actionBar != null) { + if (actionBar != null && actionBar.getBackButton() != null) { actionBar.getBackButton().setEnabled(!donePressed); } if (detailSettingsCell[0] != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 0e523d436..7ac2ae658 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -522,7 +522,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen menuItem.setSubMenuDelegate(new ActionBarMenuItem.ActionBarSubMenuItemDelegate() { @Override public void onShowSubMenu() { - showAsListItem.setText(listSort ? LocaleController.getString("ShowAsGrid", R.string.ShowAsGrid) : LocaleController.getString("ShowAsList", R.string.ShowAsList)); + showAsListItem.setText(listSort ? LocaleController.getString(R.string.ShowAsGrid) : LocaleController.getString("ShowAsList", R.string.ShowAsList)); showAsListItem.setIcon(listSort ? R.drawable.msg_media : R.drawable.msg_list); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index b71f6a9bd..5abeceefe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -145,7 +145,6 @@ import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BringAppForegroundService; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.DownloadController; import org.telegram.messenger.Emoji; @@ -238,6 +237,7 @@ import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.ShareAlert; @@ -1834,6 +1834,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private int sharedMediaType; private long topicId; private long currentDialogId; + private ReactionsLayoutInBubble.VisibleReaction currentFilterTag; + private String currentFilterQuery; + private boolean currentFiltered; private long mergeDialogId; private int totalImagesCount; private int startOffset; @@ -3929,7 +3932,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (needSearchImageInArr && isFirstLoading) { isFirstLoading = false; loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); } else if (!imagesArr.isEmpty()) { setIsAboutToSwitchToIndex(switchingToIndex, true, true); } @@ -4014,7 +4017,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (!endReached[loadIndex]) { loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); } } } else { @@ -4627,6 +4630,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat actionBar.setBackgroundColor(Theme.ACTION_BAR_PHOTO_VIEWER_COLOR); actionBar.setOccupyStatusBar(isStatusBarVisible()); actionBar.setItemsBackgroundColor(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, false); + actionBar.setItemsColor(Color.WHITE, false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBarContainer = new PhotoViewerActionBarContainer(activity); actionBar.addView(actionBarContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); @@ -11819,7 +11823,43 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat dialogPhotos = null; if (currentAnimation == null && !isEvent) { if (currentDialogId != 0 && totalImagesCount == 0 && currentMessageObject != null && !currentMessageObject.scheduled) { - if (MediaDataController.getMediaType(currentMessageObject.messageOwner) == sharedMediaType) { + /*if (currentFilterTag != null && TextUtils.isEmpty(currentFilterQuery)) { + if (needSearchImageInArr && isFirstLoading) { + isFirstLoading = false; + loadingMoreImages = true; + MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 50, 0, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); + } + } else */if (currentFiltered && parentChatActivity != null) { + ArrayList messageObjects = parentChatActivity.getFilteredMessages(); + if (messageObjects != null) { + imagesArr.clear(); + for (int i = 0; i < messageObjects.size(); ++i) { + MessageObject msg = messageObjects.get(i); + if (MediaDataController.getMediaType(msg.messageOwner) != sharedMediaType) + continue; + imagesArr.add(msg); + imagesByIds[0].put(msg.getId(), msg); + } + Collections.sort(imagesArr, (a, b) -> a.getId() - b.getId()); + currentIndex = -1; + for (int i = 0; i < imagesArr.size(); ++i) { + if (imagesArr.get(i) == currentMessageObject || imagesArr.get(i).getId() == currentMessageObject.getId()) { + currentIndex = i; + } + } + if (currentIndex < 0) { + currentIndex = imagesArr.size(); + imagesArr.add(currentMessageObject); + imagesByIds[0].put(currentMessageObject.getId(), currentMessageObject); + } + setImages(); + if (countView != null) { + countView.updateShow(true, false); + countView.set(1 + currentIndex, imagesArr.size(), false); + } + } + isFirstLoading = false; + } else if (MediaDataController.getMediaType(currentMessageObject.messageOwner) == sharedMediaType) { MediaDataController.getInstance(currentAccount).getMediaCount(currentDialogId, topicId, sharedMediaType, classGuid, true); if (mergeDialogId != 0) { MediaDataController.getInstance(currentAccount).getMediaCount(mergeDialogId, topicId, sharedMediaType, classGuid, true); @@ -12045,7 +12085,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } allowShare = !noforwards; } - if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { + if (currentFiltered && (currentFilterTag != null || !TextUtils.isEmpty(currentFilterQuery))) { + if (countView != null) { + countView.updateShow(true, animated); + countView.set(1 + switchingToIndex, imagesArr.size()); + } + } else if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { if (opennedFromMedia) { if (startOffset + imagesArr.size() < totalImagesCount + totalImagesCountMerge && !loadingMoreImages && switchingToIndex > imagesArr.size() - 5) { int loadFromMaxId = imagesArr.isEmpty() ? 0 : imagesArr.get(imagesArr.size() - 1).getId(); @@ -12058,7 +12103,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (!placeProvider.loadMore()) { - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } } @@ -12067,7 +12112,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int loadFromMinId = imagesArr.get(0).getId(); int loadIndex = 0; if (!placeProvider.loadMore()) { - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, 0, loadFromMinId, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, 0, loadFromMinId, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } } @@ -12086,7 +12131,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } if (countView != null) { @@ -14347,6 +14392,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeProvider = provider; mergeDialogId = mDialogId; currentDialogId = dialogId; + currentFilterTag = chatActivity != null ? chatActivity.getFilterTag() : null; + currentFilterQuery = chatActivity != null ? chatActivity.getFilterQuery() : null; + currentFiltered = chatActivity != null && chatActivity.isFiltered(); + this.topicId = topicId; selectedPhotosAdapter.notifyDataSetChanged(); this.pageBlocksAdapter = pageBlocksAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java index 8448234d9..3e4dfd7f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -157,10 +157,14 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification public final static int PREMIUM_FEATURE_STORIES_EXPIRATION_DURATION = 17; public final static int PREMIUM_FEATURE_STORIES_SAVE_TO_GALLERY = 18; public final static int PREMIUM_FEATURE_STORIES_LINKS_AND_FORMATTING = 19; - public static final int PREMIUM_FEATURE_STORIES_PRIORITY_ORDER = 20; - public static final int PREMIUM_FEATURE_STORIES_CAPTION = 21; + public final static int PREMIUM_FEATURE_STORIES_PRIORITY_ORDER = 20; + public final static int PREMIUM_FEATURE_STORIES_CAPTION = 21; public final static int PREMIUM_FEATURE_WALLPAPER = 22; public final static int PREMIUM_FEATURE_NAME_COLOR = 23; + public final static int PREMIUM_FEATURE_SAVED_TAGS = 24; + public final static int PREMIUM_FEATURE_STORIES_QUALITY = 25; + public final static int PREMIUM_FEATURE_LAST_SEEN = 26; + public final static int PREMIUM_FEATURE_MESSAGE_PRIVACY = 27; private int statusBarHeight; private int firstViewHeight; @@ -218,6 +222,8 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return PREMIUM_FEATURE_STORIES; case "stories__stealth_mode": return PREMIUM_FEATURE_STORIES_STEALTH_MODE; + case "stories__quality": + return PREMIUM_FEATURE_STORIES_QUALITY; case "stories__permanent_views_history": return PREMIUM_FEATURE_STORIES_VIEWS_HISTORY; case "stories__expiration_durations": @@ -234,6 +240,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return PREMIUM_FEATURE_WALLPAPER; case "peer_colors": return PREMIUM_FEATURE_NAME_COLOR; + case "saved_tags": + return PREMIUM_FEATURE_SAVED_TAGS; + case "last_seen": + return PREMIUM_FEATURE_LAST_SEEN; + case "message_privacy": + return PREMIUM_FEATURE_MESSAGE_PRIVACY; } return -1; } @@ -272,6 +284,8 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return "stories"; case PREMIUM_FEATURE_STORIES_STEALTH_MODE: return "stories__stealth_mode"; + case PREMIUM_FEATURE_STORIES_QUALITY: + return "stories__quality"; case PREMIUM_FEATURE_STORIES_VIEWS_HISTORY: return "stories__permanent_views_history"; case PREMIUM_FEATURE_STORIES_EXPIRATION_DURATION: @@ -288,6 +302,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return "wallpapers"; case PREMIUM_FEATURE_NAME_COLOR: return "peer_colors"; + case PREMIUM_FEATURE_SAVED_TAGS: + return "saved_tags"; + case PREMIUM_FEATURE_LAST_SEEN: + return "last_seen"; + case PREMIUM_FEATURE_MESSAGE_PRIVACY: + return "message_privacy"; } return null; } @@ -655,14 +675,17 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString(R.string.PremiumPreviewReactions2), LocaleController.getString(R.string.PremiumPreviewReactions2Description))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString(R.string.PremiumPreviewStickers), LocaleController.getString(R.string.PremiumPreviewStickersDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, LocaleController.getString(R.string.PremiumPreviewEmoji), LocaleController.getString(R.string.PremiumPreviewEmojiDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.msg_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString(R.string.PremiumPreviewProfileBadge), LocaleController.getString(R.string.PremiumPreviewProfileBadgeDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString(R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString(R.string.PremiumPreviewAnimatedProfilesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewTags2)), LocaleController.getString(R.string.PremiumPreviewTagsDescription2))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString(R.string.PremiumPreviewAppIcon), LocaleController.getString(R.string.PremiumPreviewAppIconDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, LocaleController.getString(R.string.PremiumPreviewEmojiStatus), LocaleController.getString(R.string.PremiumPreviewEmojiStatusDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, LocaleController.getString(R.string.PremiumPreviewTranslations), LocaleController.getString(R.string.PremiumPreviewTranslationsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewWallpaper)), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewProfileColor)), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, LocaleController.getString(R.string.PremiumPreviewWallpaper), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, LocaleController.getString(R.string.PremiumPreviewProfileColor), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewLastSeen)), LocaleController.getString(R.string.PremiumPreviewLastSeenDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewMessagePrivacy)), LocaleController.getString(R.string.PremiumPreviewMessagePrivacyDescription))); if (messagesController.premiumFeaturesTypesToPosition.size() > 0) { for (int i = 0; i < premiumFeatures.size(); i++) { @@ -1621,6 +1644,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return; } actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), true); actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false); particlesView.drawable.updateColors(); if (backgroundView != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java index 613cbf72f..b6d3a573a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java @@ -421,12 +421,10 @@ public class PrivacyControlActivity extends BaseFragment implements Notification avatarForRestPhoto = userFull.fallback_photo; } } - } } - @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -578,6 +576,18 @@ public class PrivacyControlActivity extends BaseFragment implements Notification ).show(); BotWebViewVibrationEffect.APP_ERROR.vibrate(); AndroidUtilities.shakeViewSpring(view, shakeDp = -shakeDp); + } else if (rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES && (position == myContactsRow || position == nobodyRow) && !getUserConfig().isPremium()) { + BulletinFactory.of(this).createSimpleBulletin( + R.raw.star_premium_2, + LocaleController.getString(R.string.OptionPremiumRequiredTitle), + AndroidUtilities.replaceTags(LocaleController.getString(R.string.OptionPremiumRequiredMessage)), + LocaleController.getString(R.string.OptionPremiumRequiredButton), + () -> { + presentFragment(new PremiumPreviewFragment("settings")); + } + ).show(); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.shakeViewSpring(view, shakeDp = -shakeDp); } else if (position == nobodyRow || position == everybodyRow || position == myContactsRow) { int newType; if (position == nobodyRow) { @@ -709,16 +719,20 @@ public class PrivacyControlActivity extends BaseFragment implements Notification TLRPC.TL_account_setGlobalPrivacySettings req2 = new TLRPC.TL_account_setGlobalPrivacySettings(); req2.settings = new TLRPC.TL_globalPrivacySettings(); TLRPC.TL_globalPrivacySettings settings = getContactsController().getGlobalPrivacySettings(); - req2.settings.archive_and_mute_new_noncontact_peers = settings.archive_and_mute_new_noncontact_peers; - req2.settings.keep_archived_folders = settings.keep_archived_folders; - req2.settings.keep_archived_unmuted = settings.keep_archived_unmuted; + if (settings != null) { + req2.settings.archive_and_mute_new_noncontact_peers = settings.archive_and_mute_new_noncontact_peers; + req2.settings.keep_archived_folders = settings.keep_archived_folders; + req2.settings.keep_archived_unmuted = settings.keep_archived_unmuted; + req2.settings.hide_read_marks = settings.hide_read_marks; + } req2.settings.new_noncontact_peers_require_premium = currentType == TYPE_CONTACTS; - req2.settings.hide_read_marks = settings.hide_read_marks; getConnectionsManager().sendRequest(req2, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error != null) { showErrorAlert(); } else { - settings.new_noncontact_peers_require_premium = req2.settings.new_noncontact_peers_require_premium; + if (settings != null) { + settings.new_noncontact_peers_require_premium = req2.settings.new_noncontact_peers_require_premium; + } finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated); } @@ -944,15 +958,15 @@ public class PrivacyControlActivity extends BaseFragment implements Notification initialRulesSubType = currentSubType; } - updateRows(false); if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN) { TLRPC.TL_globalPrivacySettings privacySettings = getContactsController().getGlobalPrivacySettings(); selectedReadValue = currentReadValue = privacySettings != null && privacySettings.hide_read_marks; } + updateRows(false); } private boolean hasChanges() { - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && currentType != TYPE_EVERYBODY && currentReadValue != selectedReadValue) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && (currentType != TYPE_EVERYBODY || currentMinus != null && !currentMinus.isEmpty()) && currentReadValue != selectedReadValue) { return true; } if (initialRulesType != currentType) { @@ -1033,7 +1047,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification phoneContactsRow = rowCount++; } detailRow = rowCount++; - if (rulesType != PRIVACY_RULES_TYPE_MESSAGES) { + if (rulesType != PRIVACY_RULES_TYPE_MESSAGES && (rulesType != PRIVACY_RULES_TYPE_VOICE_MESSAGES || getUserConfig().isPremium())) { shareSectionRow = rowCount++; if (currentType == TYPE_NOBODY || currentType == TYPE_CONTACTS) { alwaysShareRow = rowCount++; @@ -1055,11 +1069,11 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } photoForRestDescriptionRow = rowCount++; } - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && currentType != TYPE_EVERYBODY) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && (currentType != TYPE_EVERYBODY || currentMinus != null && !currentMinus.isEmpty())) { readRow = rowCount++; readDetailRow = rowCount++; } - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getUserConfig().isPremium() && !getMessagesController().premiumFeaturesBlocked()) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getMessagesController().premiumFeaturesBlocked()) { readPremiumRow = rowCount++; readPremiumDetailRow = rowCount++; } @@ -1156,7 +1170,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification return; } - if (currentType != 0 && rulesType == PRIVACY_RULES_TYPE_LASTSEEN) { + if (currentType != 0 && rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getUserConfig().isPremium()) { final SharedPreferences preferences = MessagesController.getGlobalMainSettings(); boolean showed = preferences.getBoolean("privacyAlertShowed", false); if (!showed) { @@ -1361,7 +1375,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } textCell.setTextAndValue(LocaleController.getString("PrivacyP2P2", R.string.PrivacyP2P2), value, false); } else if (position == readPremiumRow) { - textCell.setText(LocaleController.getString(R.string.PrivacyLastSeenPremium), false); + textCell.setText(LocaleController.getString(getUserConfig().isPremium() ? R.string.PrivacyLastSeenPremiumForPremium : R.string.PrivacyLastSeenPremium), false); textCell.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlueText)); } break; @@ -1373,6 +1387,13 @@ public class PrivacyControlActivity extends BaseFragment implements Notification presentFragment(new PremiumPreviewFragment("noncontacts")); })); backgroundResId = R.drawable.greydivider_bottom; + } else if (position == detailRow && rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES) { + privacyCell.setText(LocaleController.getString(R.string.PrivacyVoiceMessagesInfo)); + if (getUserConfig().isPremium()) { + backgroundResId = R.drawable.greydivider; + } else { + backgroundResId = R.drawable.greydivider_bottom; + } } else if (position == detailRow) { if (rulesType == PRIVACY_RULES_TYPE_PHONE) { if (prevSubtypeContacts = (currentType == TYPE_NOBODY && currentSubType == 1)) { @@ -1411,10 +1432,8 @@ public class PrivacyControlActivity extends BaseFragment implements Notification privacyCell.setText(LocaleController.getString("WhoCanCallMeInfo", R.string.WhoCanCallMeInfo)); } else if (rulesType == PRIVACY_RULES_TYPE_INVITE) { privacyCell.setText(LocaleController.getString("WhoCanAddMeInfo", R.string.WhoCanAddMeInfo)); - } else if (rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES) { - privacyCell.setText(LocaleController.getString(R.string.PrivacyVoiceMessagesInfo)); } else { - privacyCell.setText(LocaleController.getString("CustomHelp", R.string.CustomHelp)); + privacyCell.setText(LocaleController.getString(R.string.CustomHelp)); } backgroundResId = R.drawable.greydivider; } else if (position == shareDetailRow) { @@ -1456,7 +1475,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification privacyCell.setText(LocaleController.getString(R.string.HideReadTimeInfo)); backgroundResId = readPremiumDetailRow == -1 ? R.drawable.greydivider_bottom : R.drawable.greydivider; } else if (position == readPremiumDetailRow) { - privacyCell.setText(LocaleController.getString(R.string.PrivacyLastSeenPremiumInfo)); + privacyCell.setText(LocaleController.getString(getUserConfig().isPremium() ? R.string.PrivacyLastSeenPremiumInfoForPremium : R.string.PrivacyLastSeenPremiumInfo)); backgroundResId = R.drawable.greydivider_bottom; } if (backgroundResId != 0) { @@ -1509,17 +1528,20 @@ public class PrivacyControlActivity extends BaseFragment implements Notification radioCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), currentType == TYPE_EVERYBODY, true); } } else if (position == myContactsRow) { + if ((rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES || rulesType == PRIVACY_RULES_TYPE_MESSAGES) && !getUserConfig().isPremium()) { + radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); + } if (rulesType == PRIVACY_RULES_TYPE_P2P) { radioCell.setText(LocaleController.getString("P2PContacts", R.string.P2PContacts), currentType == TYPE_CONTACTS, nobodyRow != -1); } else if (rulesType == PRIVACY_RULES_TYPE_MESSAGES) { - if (!getUserConfig().isPremium()) { - radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); - } radioCell.setText(LocaleController.getString(R.string.PrivacyMessagesContactsAndPremium), currentType == TYPE_CONTACTS, nobodyRow != -1); } else { radioCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), currentType == TYPE_CONTACTS, nobodyRow != -1); } } else { + if ((rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES || rulesType == PRIVACY_RULES_TYPE_MESSAGES) && !getUserConfig().isPremium()) { + radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); + } if (rulesType == PRIVACY_RULES_TYPE_P2P) { radioCell.setText(LocaleController.getString("P2PNobody", R.string.P2PNobody), currentType == TYPE_NOBODY, false); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 515ca866b..5848f8b57 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -8,12 +8,20 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.content.DialogInterface; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.DynamicDrawableSpan; +import android.text.style.ImageSpan; import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; @@ -51,9 +59,11 @@ import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.TextStyleSpan; @@ -297,7 +307,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio for (int a = 0; a < items.length; a++) { RadioColorCell cell = new RadioColorCell(getParentActivity()); - cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setPadding(dp(4), 0, dp(4), 0); cell.setTag(a); cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); cell.setTextAndValue(items[a], selected == a); @@ -354,16 +364,6 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } else if (position == forwardsRow) { presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_FORWARDS)); } else if (position == voicesRow) { - if (!getUserConfig().isPremium()) { - try { - fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } catch (Exception e) { - FileLog.e(e); - } - BulletinFactory.of(this).createRestrictVoiceMessagesPremiumBulletin().show(); - return; - } - presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_VOICE_MESSAGES)); } else if (position == noncontactsRow) { presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_MESSAGES)); @@ -519,7 +519,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio CheckBoxCell checkBoxCell = new CheckBoxCell(getParentActivity(), 1, 21, null); checkBoxCell.setTag(a); checkBoxCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - checkBoxCell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + checkBoxCell.setPadding(dp(4), 0, dp(4), 0); linearLayout.addView(checkBoxCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); checkBoxCell.setText(name, null, true, false); checkBoxCell.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); @@ -1012,19 +1012,12 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } else { value = formatRulesString(getAccountInstance(), ContactsController.PRIVACY_RULES_TYPE_VOICE_MESSAGES); } - textCell.setTextAndValue(LocaleController.getString(R.string.PrivacyVoiceMessages), value, noncontactsRow != -1); + textCell.setTextAndValue(addPremiumStar(LocaleController.getString(R.string.PrivacyVoiceMessages)), value, noncontactsRow != -1); ImageView imageView = textCell.getValueImageView(); - if (!getUserConfig().isPremium()) { - imageView.setVisibility(View.VISIBLE); - imageView.setImageResource(R.drawable.msg_mini_premiumlock); - imageView.setTranslationY(AndroidUtilities.dp(1)); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), PorterDuff.Mode.MULTIPLY)); - } else { - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); - } + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); } else if (position == noncontactsRow) { value = LocaleController.getString(noncontactsValue ? R.string.ContactsAndPremium : R.string.P2PEverybody); - textCell.setTextAndValue(LocaleController.getString(R.string.PrivacyMessages), value, false); + textCell.setTextAndValue(addPremiumStar(LocaleController.getString(R.string.PrivacyMessages)), value, false); } else if (position == passportRow) { textCell.setText(LocaleController.getString("TelegramPassport", R.string.TelegramPassport), true); } else if (position == deleteAccountRow) { @@ -1230,6 +1223,20 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } } + private SpannableString premiumStar; + private CharSequence addPremiumStar(String text) { + if (!getUserConfig().isPremium()) { + return text; + } + if (premiumStar == null) { + premiumStar = new SpannableString("★"); + Drawable drawable = new AnimatedEmojiDrawable.WrapSizeDrawable(PremiumGradient.getInstance().premiumStarMenuDrawable, dp(18), dp(18)); + drawable.setBounds(0, 0, dp(18), dp(18)); + premiumStar.setSpan(new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_CENTER), 0, premiumStar.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + return new SpannableStringBuilder(text).append("  ").append(premiumStar); + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index d6380b3a9..5f757deab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -160,6 +160,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.INavigationLayout; +import org.telegram.ui.ActionBar.OKLCH; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -1953,11 +1954,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. updateStoriesViewBounds(false); } }; - actionBar.setColorFilterMode(PorterDuff.Mode.SRC_IN); actionBar.setForceSkipTouches(true); actionBar.setBackgroundColor(Color.TRANSPARENT); actionBar.setItemsBackgroundColor(peerColor != null ? 0x20ffffff : getThemedColor(Theme.key_avatar_actionBarSelectorBlue), false); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), true); actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setCastShadows(false); actionBar.setAddToContainer(false); @@ -2996,17 +2997,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected int processColor(int color) { return applyPeerColor(color, false); } - @Override protected void onSelectedTabChanged() { updateSelectedMediaTabText(); } - - @Override - protected boolean canShowSearchItem() { - return mediaHeaderVisible; - } - @Override protected boolean includeSavedDialogs() { return dialogId == getUserConfig().getClientUserId() && !saved; @@ -3087,6 +3081,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. searchItem.setContentDescription(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); searchItem.setSearchFieldHint(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); sharedMediaLayout.getSearchItem().setVisibility(View.GONE); + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setVisibility(View.GONE); + } if (expandPhoto) { searchItem.setVisibility(View.GONE); } @@ -3686,8 +3683,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. BuildVars.DEBUG_VERSION ? (SharedConfig.useSurfaceInStories ? "back to TextureView in stories" : "use SurfaceView in stories") : null, BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.photoViewerBlur ? "do not blur in photoviewer" : "blur in photoviewer") : null, !SharedConfig.payByInvoice ? "Enable Invoice Payment" : "Disable Invoice Payment", - BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null, - BuildVars.DEBUG_PRIVATE_VERSION ? ((SharedConfig.forceLessData ? "Disable using less data" : "Use less data on stories") + (ApplicationLoader.isConnectionSlow() ? " (connection is already slow)" : "")) : null + BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null }; builder.setItems(items, (dialog, which) -> { @@ -3721,7 +3717,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getMessagesStorage().clearSentMedia(); SharedConfig.setNoSoundHintShowed(false); SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); - editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").remove("taptostorysoundhint").remove("nothanos").remove("voiceoncehint").remove("savedhint").apply(); + editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").remove("taptostorysoundhint").remove("nothanos").remove("voiceoncehint").remove("savedhint").remove("savedsearchhint").remove("savedsearchtaghint").apply(); MessagesController.getEmojiSettings(currentAccount).edit().remove("featured_hidden").remove("emoji_featured_hidden").commit(); SharedConfig.textSelectionHintShows = 0; SharedConfig.lockRecordAudioVideoHint = 0; @@ -3747,7 +3743,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (which == 8) { SharedConfig.toggleRoundCamera16to9(); } else if (which == 9) { - ((LaunchActivity) getParentActivity()).checkAppUpdate(true); + ((LaunchActivity) getParentActivity()).checkAppUpdate(true, null); } else if (which == 10) { getMessagesStorage().readAllDialogs(-1); } else if (which == 11) { @@ -3930,8 +3926,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. SharedConfig.togglePaymentByInvoice(); } else if (which == 26) { getMediaDataController().loadAttachMenuBots(false, true); - } else if (which == 27) { - SharedConfig.setForceLessData(!SharedConfig.forceLessData); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -5970,6 +5964,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. headerShadowAnimatorSet.cancel(); } ActionBarMenuItem mediaSearchItem = sharedMediaLayout.getSearchItem(); + ImageView mediaOptionsItem = sharedMediaLayout.getSearchOptionsItem(); if (!mediaHeaderVisible) { if (callItemVisible) { callItem.setVisibility(View.VISIBLE); @@ -5981,14 +5976,22 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. editItem.setVisibility(View.VISIBLE); } otherItem.setVisibility(View.VISIBLE); + if (mediaOptionsItem != null) { + mediaOptionsItem.setVisibility(View.GONE); + } } else { if (sharedMediaLayout.isSearchItemVisible()) { mediaSearchItem.setVisibility(View.VISIBLE); } + if (mediaOptionsItem != null) { + mediaOptionsItem.setVisibility(View.VISIBLE); + } if (sharedMediaLayout.isCalendarItemVisible()) { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); + sharedMediaLayout.animateSearchToOptions(true, false); } else { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.INVISIBLE); + sharedMediaLayout.animateSearchToOptions(false, false); } } updateStoriesViewBounds(false); @@ -7243,9 +7246,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (isOpen) { if (imageUpdater != null) { - transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.userInfoDidLoad}); + transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needCheckSystemBarColors}); } else { - transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad}); + transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.needCheckSystemBarColors}); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !backward && getParentActivity() != null) { navigationBarAnimationColorFrom = getParentActivity().getWindow().getNavigationBarColor(); @@ -8354,7 +8357,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { isOnline[0] = false; newString2 = LocaleController.formatUserStatus(currentAccount, user, isOnline, shortStatus ? new boolean[1] : null); - hiddenStatusButton = user != null && !getUserConfig().isPremium() && user.status != null && user.status.by_me; + hiddenStatusButton = user != null && !isOnline[0] && !getUserConfig().isPremium() && user.status != null && (user.status instanceof TLRPC.TL_userStatusRecently || user.status instanceof TLRPC.TL_userStatusLastMonth || user.status instanceof TLRPC.TL_userStatusLastWeek) && user.status.by_me; if (onlineTextView[1] != null && !mediaHeaderVisible) { int key = isOnline[0] && peerColor == null ? Theme.key_profile_status : Theme.key_avatar_subtitleInProfileBlue; onlineTextView[1].setTag(key); @@ -8798,6 +8801,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } private void updatedPeerColor() { + adaptedColors.clear(); if (topView != null) { topView.setBackgroundColorId(peerColor, true); } @@ -8843,6 +8847,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ((TextDetailCell) view).valueTextView.setTextColor(applyPeerColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false)); } else if (view instanceof TextCell) { ((TextCell) view).updateColors(); + } else if (view instanceof AboutLinkCell) { + ((AboutLinkCell) view).updateColors(); } else if (view instanceof NotificationsCheckCell) { ((NotificationsCheckCell) view).getCheckBox().invalidate(); } @@ -8862,9 +8868,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return applyPeerColor(color, actionBar, null); } + private final SparseIntArray adaptedColors = new SparseIntArray(); private int applyPeerColor(int color, boolean actionBar, Boolean online) { if (!actionBar) return color; if (peerColor != null) { + if (!actionBar) { + int index = adaptedColors.indexOfKey(color); + if (index < 0) { + final int baseColor = Theme.adaptHSV(peerColor.getBgColor1(Theme.isCurrentThemeDark()), Theme.isCurrentThemeDark() ? 0 : +.05f, Theme.isCurrentThemeDark() ? -.1f : -.04f); + int adapted = OKLCH.adapt(color, baseColor); + adaptedColors.put(color, adapted); + return adapted; + } else { + return adaptedColors.valueAt(index); + } + } final int baseColor = getThemedColor(actionBar ? Theme.key_actionBarDefault : Theme.key_windowBackgroundWhiteBlueIcon); final int storyColor = ColorUtils.blendARGB(peerColor.getStoryColor1(Theme.isCurrentThemeDark()), peerColor.getStoryColor2(Theme.isCurrentThemeDark()), .5f); int accentColor = actionBar ? storyColor : peerColor.getBgColor1(Theme.isCurrentThemeDark()); @@ -9827,6 +9845,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected void didResizeStart() { layoutManager.mIgnoreTopPadding = true; } + + @Override + protected int processColor(int color) { + return applyPeerColor(color, false); + } }; break; } @@ -10151,7 +10174,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. detailCell.setImageClickListener(null); } detailCell.setTag(position); - detailCell.valueTextView.setTextColor(applyPeerColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false)); break; case VIEW_TYPE_ABOUT_LINK: AboutLinkCell aboutLinkCell = (AboutLinkCell) holder.itemView; @@ -10241,7 +10263,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (position == addMemberRow) { textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); - textCell.setTextAndIcon(LocaleController.getString("AddMember", R.string.AddMember), R.drawable.msg_contact_add, membersSectionRow == -1); + boolean isNextPositionMember = position + 1 >= membersStartRow && position + 1 < membersEndRow; + textCell.setTextAndIcon(LocaleController.getString("AddMember", R.string.AddMember), R.drawable.msg_contact_add, membersSectionRow == -1 || isNextPositionMember); } else if (position == sendMessageRow) { textCell.setText(LocaleController.getString("SendMessageLocation", R.string.SendMessageLocation), true); } else if (position == addToContactsRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index b81c9b8d3..74f253fdc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -147,6 +147,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public final static int TYPE_EXPANDABLE_REACTIONS = 8; public final static int TYPE_EMOJI_STATUS_CHANNEL = 9; public final static int TYPE_EMOJI_STATUS_CHANNEL_TOP = 10; + public final static int TYPE_TAGS = 11; public boolean isBottom() { return type == TYPE_SET_REPLY_ICON || type == TYPE_EMOJI_STATUS_CHANNEL_TOP; @@ -686,7 +687,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati updateTabsPosition(layoutManager.findFirstCompletelyVisibleItemPosition()); } updateSearchBox(); - AndroidUtilities.updateViewVisibilityAnimated(emojiTabsShadow, emojiGridView.computeVerticalScrollOffset() != 0 || type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL_TOP || type == TYPE_REACTIONS || type == TYPE_CHAT_REACTIONS, 1f, true); + AndroidUtilities.updateViewVisibilityAnimated(emojiTabsShadow, emojiGridView.computeVerticalScrollOffset() != 0 || type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL_TOP || type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_CHAT_REACTIONS, 1f, true); invalidateParent(); } @@ -820,7 +821,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati TextView emptyViewText = new TextView(context); if (type == TYPE_AVATAR_CONSTRUCTOR) { emptyViewText.setText(LocaleController.getString("NoEmojiOrStickersFound", R.string.NoEmojiOrStickersFound)); - } else if (type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { + } else if (type == TYPE_EMOJI_STATUS || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { emptyViewText.setText(LocaleController.getString("NoEmojiFound", R.string.NoEmojiFound)); } else if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { emptyViewText.setText(LocaleController.getString("NoReactionsFound", R.string.NoReactionsFound)); @@ -893,6 +894,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati RecyclerListView.OnItemLongClickListenerExtended onItemLongClick = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { + if (type == TYPE_TAGS) return false; if (view instanceof ImageViewEmoji && (type == TYPE_REACTIONS || type == TYPE_EXPANDABLE_REACTIONS)) { incrementHintUse(); performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); @@ -999,14 +1001,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } else { onEmojiClick(viewEmoji, viewEmoji.span); } - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} } } else if (view instanceof ImageView) { onEmojiClick(view, null); - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} @@ -1014,7 +1016,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } else if (view instanceof EmojiPackExpand) { EmojiPackExpand button = (EmojiPackExpand) view; expand(position, button); - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} @@ -1732,7 +1734,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (result.get(i).emoji.startsWith("animated_")) { documentIds.add(Long.parseLong(result.get(i).emoji.substring(9))); } else { - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION) { TLRPC.TL_availableReaction reaction = availableReactions.get(result.get(i).emoji); if (reaction != null) { reactions.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction)); @@ -1870,7 +1872,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati stickersSearchResult.clear(); } emojiSearchGridView.scrollToPosition(0); - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION) { if (!reactions.isEmpty()) { searchResult.addAll(reactions); } else { @@ -2546,7 +2548,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private void clearRecent() { - if (type == TYPE_REACTIONS && onRecentClearedListener != null) { + if ((type == TYPE_REACTIONS || type == TYPE_TAGS) && onRecentClearedListener != null) { onRecentClearedListener.onRecentCleared(); } } @@ -3065,9 +3067,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati createImageReceiver(parent); SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); if (type == TYPE_CHAT_REACTIONS) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - ImageLocation thumbLocation = ImageLocation.getForDocument(thumb, document); - imageReceiver.setImage(ImageLocation.getForDocument(document), !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? "34_34_firstframe" : "34_34", thumbLocation, null, svgThumb, document.size, null, document, 0); + imageReceiver.setImage(ImageLocation.getForDocument(document), !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? "34_34_firstframe" : "34_34", null, null, svgThumb, document.size, null, document, 0); } else { imageReceiver.setImage(ImageLocation.getForDocument(document), "100_100_firstframe", null, null, svgThumb, 0, "tgs", document, 0); } @@ -3164,7 +3164,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati return; } MediaDataController.getInstance(account).checkStickers(MediaDataController.TYPE_EMOJIPACKS); - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_CHAT_REACTIONS) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_CHAT_REACTIONS) { MediaDataController.getInstance(account).checkReactions(); } else if (type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { if (MessagesController.getInstance(account).getMainSettings().getBoolean("resetemojipacks", true)) { @@ -3335,7 +3335,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } - if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TOPIC_ICON && type != TYPE_CHAT_REACTIONS && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON && type != TYPE_SET_REPLY_ICON_BOTTOM) { + if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TAGS && type != TYPE_TOPIC_ICON && type != TYPE_CHAT_REACTIONS && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON && type != TYPE_SET_REPLY_ICON_BOTTOM) { longtapHintRow = totalCount++; rowHashCodes.add(6L); } @@ -3351,7 +3351,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (recentReactionsToSet != null) { topReactionsStartRow = totalCount; ArrayList tmp = new ArrayList<>(recentReactionsToSet); - if (type == TYPE_EXPANDABLE_REACTIONS) { + if (type == TYPE_EXPANDABLE_REACTIONS || type == TYPE_TAGS) { topReactions.addAll(tmp); } else { for (int i = 0; i < 16; i++) { @@ -3366,7 +3366,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati totalCount += topReactions.size(); topReactionsEndRow = totalCount; - if (!tmp.isEmpty() && type != TYPE_EXPANDABLE_REACTIONS) { + if (!tmp.isEmpty() && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_TAGS) { boolean allRecentReactionsIsDefault = true; for (int i = 0; i < tmp.size(); i++) { if (tmp.get(i).documentId != 0) { @@ -4732,7 +4732,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (categoriesListView != null || getContext() == null) { return; } - if (type != TYPE_REACTIONS && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_EMOJI_STATUS && type != TYPE_AVATAR_CONSTRUCTOR) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_EMOJI_STATUS && type != TYPE_AVATAR_CONSTRUCTOR) { return; } @@ -4745,6 +4745,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati categoriesType = StickerCategoriesListView.CategoriesType.PROFILE_PHOTOS; break; case TYPE_REACTIONS: + case TYPE_TAGS: default: categoriesType = StickerCategoriesListView.CategoriesType.DEFAULT; break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index 04c665a52..3f31757d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -789,6 +789,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle), Theme.getColor(Theme.key_player_actionBarSubtitle)); actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarTitle), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarTitle), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); 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 b84e451e0..3f5a680b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -12,6 +12,7 @@ import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -109,6 +110,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.AvatarSpan; import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.ChatActivity; +import org.telegram.ui.ChooseSpeedLayout; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -152,6 +154,7 @@ import org.telegram.ui.Components.ReactionsContainerLayout; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.SpeedIconDrawable; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TranslateAlert2; import org.telegram.ui.Components.URLSpanMono; @@ -167,6 +170,7 @@ import org.telegram.ui.NotificationsCustomSettingsActivity; import org.telegram.ui.PinchToZoomHelper; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.CaptionContainerView; import org.telegram.ui.Stories.recorder.HintView2; import org.telegram.ui.Stories.recorder.StoryEntry; @@ -361,6 +365,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica private float viewsThumbPivotY; private boolean userCanSeeViews; + private ChooseSpeedLayout speedLayout; + private ActionBarMenuSubItem speedItem; + public PeerStoriesView(@NonNull Context context, StoryViewer storyViewer, SharedResources sharedResources, Theme.ResourcesProvider resourcesProvider) { super(context); pinchToZoomHelper.setCallback(new PinchToZoomHelper.Callback() { @@ -1144,7 +1151,10 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica MessagesController.getInstance(currentAccount).getStoriesController().loadSendAs(); MessagesController.getInstance(currentAccount).getStoriesController().getDraftsController().load(); } - popupMenu = new CustomPopupMenu(getContext(), resourcesProvider, isSelf) { + final boolean userCanEditStory = isSelf || MessagesController.getInstance(currentAccount).getStoriesController().canEditStory(currentStory.storyItem); + final boolean canEditStory = isSelf || (isChannel && userCanEditStory); + final boolean speedControl = currentStory.isVideo; + popupMenu = new CustomPopupMenu(getContext(), resourcesProvider, speedControl) { private boolean edit; private void addViewStatistics(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, TL_stories.StoryItem storyItem) { @@ -1181,10 +1191,61 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } + private void addSpeedLayout(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, boolean addGap) { + if (!speedControl || currentStory != null && currentStory.uploadingStory != null) { + speedLayout = null; + speedItem = null; + return; + } + + speedLayout = new ChooseSpeedLayout(getContext(), popupLayout.getSwipeBack(), new ChooseSpeedLayout.Callback() { + @Override + public void onSpeedSelected(float speed, boolean isFinal, boolean closeMenu) { + if (storyViewer != null) { + storyViewer.setSpeed(speed); + } + updateSpeedItem(isFinal); + if (closeMenu && popupLayout.getSwipeBack() != null) { + popupLayout.getSwipeBack().closeForeground(); + } + } + }); + speedLayout.update(StoryViewer.currentSpeed, true); + + speedItem = new ActionBarMenuSubItem(getContext(), false, false, false, resourcesProvider); + speedItem.setTextAndIcon(LocaleController.getString(R.string.Speed), R.drawable.msg_speed, null); + updateSpeedItem(true); + speedItem.setMinimumWidth(AndroidUtilities.dp(196)); + speedItem.setRightIcon(R.drawable.msg_arrowright); + popupLayout.addView(speedItem); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) speedItem.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.gravity = Gravity.RIGHT; + } + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(48); + speedItem.setLayoutParams(layoutParams); + int swipeBackIndex = popupLayout.addViewToSwipeBack(speedLayout.speedSwipeBackLayout); + speedItem.openSwipeBackLayout = () -> { + if (popupLayout.getSwipeBack() != null) { + popupLayout.getSwipeBack().openForeground(swipeBackIndex); + } + }; + speedItem.setOnClickListener(view -> { + speedItem.openSwipeBack(); + }); + + popupLayout.swipeBackGravityRight = true; + + if (addGap) { + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), resourcesProvider, Theme.key_actionBarDefaultSubmenuSeparator); + gap.setTag(R.id.fit_width_tag, 1); + popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + } + } + @Override protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout) { - final boolean userCanEditStory = isSelf || MessagesController.getInstance(currentAccount).getStoriesController().canEditStory(currentStory.storyItem); - boolean canEditStory = isSelf || (isChannel && userCanEditStory); if (canEditStory || currentStory.uploadingStory != null) { TL_stories.StoryItem storyItem = currentStory.storyItem; if (currentStory.uploadingStory != null) { @@ -1215,7 +1276,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } }); item.setItemHeight(56); - + } + addSpeedLayout(popupLayout, false); + if (isSelf || speedControl) { ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), resourcesProvider, Theme.key_actionBarDefaultSubmenuSeparator); gap.setTag(R.id.fit_width_tag, 1); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); @@ -1389,6 +1452,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica // } // }); + addSpeedLayout(popupLayout, true); final String key = NotificationsController.getSharedPrefKey(dialogId, 0); boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId); @@ -1459,6 +1523,10 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } + if (!MessagesController.getInstance(currentAccount).premiumFeaturesBlocked() && currentStory.isVideo) { + createQualityItem(popupLayout); + } + if (!unsupported && allowShare) { if (UserConfig.getInstance(currentAccount).isPremium()) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), false, resourcesProvider).setOnClickListener(v -> { @@ -1500,7 +1568,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica createStealthModeItem(popupLayout); } if (allowShareLink) { - ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { + ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link2, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { AndroidUtilities.addToClipboard(currentStory.createLink()); onLinkCopied(); if (popupMenu != null) { @@ -1754,6 +1822,92 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } + private void createQualityItem(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout) { + final boolean qualityFull = MessagesController.getInstance(currentAccount).storyQualityFull; + if (UserConfig.getInstance(currentAccount).isPremium()) { + ActionBarMenuItem.addItem(popupLayout, qualityFull ? R.drawable.menu_quality_sd : R.drawable.menu_quality_hd, LocaleController.getString(qualityFull ? R.string.StoryQualityDecrease : R.string.StoryQualityIncrease), false, resourcesProvider).setOnClickListener(v -> { + final boolean newQualityFull = !qualityFull; + MessagesController.getInstance(currentAccount).setStoryQuality(newQualityFull); + BulletinFactory.of(storyContainer, resourcesProvider) + .createSimpleBulletin( + R.raw.chats_infotip, + LocaleController.getString(newQualityFull ? R.string.StoryQualityIncreasedTitle : R.string.StoryQualityDecreasedTitle), + LocaleController.getString(newQualityFull ? R.string.StoryQualityIncreasedMessage : R.string.StoryQualityDecreasedMessage) + ) + .show(); + if (popupMenu != null) { + popupMenu.dismiss(); + } + }); + } else { + Drawable lockIcon2 = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + lockIcon2.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable2 = new CombinedDrawable( + ContextCompat.getDrawable(getContext(), R.drawable.menu_quality_hd2), + lockIcon2 + ) { + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + }; + combinedDrawable2.setIconSize(dp(24), dp(24)); + combinedDrawable2.setIconOffset(dp(1), -dp(2)); + ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.menu_quality_hd, LocaleController.getString(R.string.StoryQualityIncrease), false, resourcesProvider); + item2.setOnClickListener(v -> { + BottomSheet sheet = new BottomSheet(getContext(), false, resourcesProvider); + sheet.fixNavigationBar(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + LinearLayout layout = new LinearLayout(getContext()); + layout.setOrientation(LinearLayout.VERTICAL); + layout.setPadding(dp(16), 0, dp(16), 0); + + BackupImageView imageView = new BackupImageView(getContext()); + imageView.getImageReceiver().setAutoRepeat(1); +// imageView.setScaleType(ImageView.ScaleType.CENTER); +// imageView.setAutoRepeat(true); +// imageView.setAnimation(R.raw.utyan_cache, 150, 150); + MediaDataController.getInstance(currentAccount).setPlaceholderImage(imageView, AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME_2, "😎", "150_150"); + layout.addView(imageView, LayoutHelper.createLinear(150, 150, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + + TextView headerView = new TextView(getContext()); + headerView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + headerView.setGravity(Gravity.CENTER); + headerView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + headerView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + headerView.setText(LocaleController.getString(R.string.StoryQualityPremium)); + layout.addView(headerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 0, 12, 0)); + + TextView descriptionView = new TextView(getContext()); + descriptionView.setGravity(Gravity.CENTER); + descriptionView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + descriptionView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + descriptionView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.StoryQualityPremiumText))); + layout.addView(descriptionView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 9, 32, 19)); + + ButtonWithCounterView button = new ButtonWithCounterView(getContext(), resourcesProvider); + button.setText(LocaleController.getString(R.string.StoryQualityIncrease), false); + SpannableStringBuilder lock = new SpannableStringBuilder("l"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.mini_switch_lock); + coloredImageSpan.setTopOffset(1); + lock.setSpan(coloredImageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + button.setSubText(new SpannableStringBuilder().append(lock).append(LocaleController.getString(R.string.OptionPremiumRequiredTitle)), false); + layout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_HORIZONTAL)); + button.setOnClickListener(view -> { + delegate.showDialog(new PremiumFeatureBottomSheet(storyViewer.fragment, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, false)); + sheet.dismiss(); + }); + + sheet.setCustomView(layout); + delegate.showDialog(sheet); + if (popupMenu != null) { + popupMenu.dismiss(); + } + }); + item2.setIcon(combinedDrawable2); + } + } + private void showLikesReaction(boolean show) { if (likesReactionShowing == show || currentStory.storyItem == null) { return; @@ -2103,6 +2257,29 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica bulletin.show(); } + private void updateSpeedItem(boolean isFinal) { + if (speedItem == null || speedLayout == null) return; + if (speedItem.getVisibility() != View.VISIBLE) { + return; + } + if (isFinal) { + if (Math.abs(StoryViewer.currentSpeed - 0.2f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedVerySlow)); + } else if (Math.abs(StoryViewer.currentSpeed - 0.5f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedSlow)); + } else if (Math.abs(StoryViewer.currentSpeed - 1.0f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedNormal)); + } else if (Math.abs(StoryViewer.currentSpeed - 1.5f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedFast)); + } else if (Math.abs(StoryViewer.currentSpeed - 2f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedVeryFast)); + } else { + speedItem.setSubtext(LocaleController.formatString(R.string.VideoSpeedCustom, SpeedIconDrawable.formatNumber(StoryViewer.currentSpeed) + "x")); + } + } + speedLayout.update(StoryViewer.currentSpeed, isFinal); + } + private void createEnterView() { Theme.ResourcesProvider emojiResourceProvider = new WrappedResourceProvider(resourcesProvider) { @Override @@ -3152,7 +3329,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica buttonTextView.setOnClickListener(v -> { if (ApplicationLoader.isStandaloneBuild()) { if (LaunchActivity.instance != null) { - LaunchActivity.instance.checkAppUpdate(true); + LaunchActivity.instance.checkAppUpdate(true, null); } } else if (BuildVars.isHuaweiStoreApp()){ Browser.openUrl(getContext(), BuildVars.HUAWEI_STORE_URL); @@ -3449,6 +3626,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } // sharedResources.muteDrawable.addView(muteIconView); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storyQualityUpdate); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stealthModeChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesLimitUpdate); @@ -3481,6 +3659,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } //sharedResources.muteDrawable.removeView(muteIconView); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storyQualityUpdate); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stealthModeChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesLimitUpdate); @@ -3519,6 +3698,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (editStoryItem != null) { editStoryItem.animate().alpha(storiesController.hasUploadingStories(dialogId) && currentStory.isVideo && !SharedConfig.allowPreparingHevcPlayers() ? .5f : 1f).start(); } + } else if (id == NotificationCenter.storyQualityUpdate) { + updatePosition(); } else if (id == NotificationCenter.emojiLoaded) { storyCaptionView.captionTextview.invalidate(); } else if (id == NotificationCenter.stealthModeChanged) { @@ -6038,7 +6219,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica sparseIntArray.put(Theme.key_chat_emojiPanelBackground, ColorUtils.setAlphaComponent(Color.WHITE, 30)); } }); - reactionsContainerLayout.setHint(LocaleController.getString("StoryReactionsHint", R.string.StoryReactionsHint)); + reactionsContainerLayout.setHint(LocaleController.getString(R.string.StoryReactionsHint)); reactionsContainerLayout.skipEnterAnimation = true; addView(reactionsContainerLayout, reactionsContainerIndex, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 52 + 20, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 64)); reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { 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 c5bb95363..6815f1835 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java @@ -37,6 +37,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; @@ -180,6 +181,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif private void updateStories(boolean animated, boolean asUpdate) { final boolean me = dialogId == UserConfig.getInstance(currentAccount).getClientUserId(); + final int now = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); TL_stories.PeerStories userFullStories = MessagesController.getInstance(currentAccount).getStoriesController().getStoriesFromFullPeer(dialogId); TL_stories.PeerStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(dialogId); final TL_stories.PeerStories userStories; @@ -241,6 +243,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif continue; } } + if (storyItem.expire_date != 0 && now > storyItem.expire_date) { + continue; + } if (me || storyItem.id > max_read_id) { storiesToShow.add(storyItem); if (storiesToShow.size() >= CIRCLES_MAX) { @@ -280,6 +285,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } + if (storyItem.expire_date != 0 && now > storyItem.expire_date) { + continue; + } if (!storiesToShow.contains(storyItem)) { storiesToShow.add(storyItem); if (storiesToShow.size() >= CIRCLES_MAX) { 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 064d40da7..d094850b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -1351,7 +1351,13 @@ public class StoriesController { HashSet loadingAllStories = new HashSet<>(); void loadSkippedStories(long dialogId) { - loadSkippedStories(getStories(dialogId), false); + boolean profile = false; + TL_stories.PeerStories peerStories = getStories(dialogId); + if (peerStories == null) { + profile = true; + peerStories = getStoriesFromFullPeer(dialogId); + } + loadSkippedStories(peerStories, profile); } void loadSkippedStories(TL_stories.PeerStories userStories, boolean profile) { 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 22092b5e7..6f87a6de0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -198,6 +198,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat private boolean isBulletinVisible; public boolean isTranslating = false; + public static float currentSpeed = 1f; + public boolean isLongpressed; Runnable longPressRunnable = () -> setLongPressed(true); @@ -274,6 +276,24 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat this.fragment = fragment; } + public void setSpeed(float speed) { + currentSpeed = speed; + if (playerHolder != null) { + playerHolder.setSpeed(speed); + StoryViewer otherStoryViewer = null; + if (fragment != null) { + if (fragment.overlayStoryViewer != this) { + otherStoryViewer = fragment.overlayStoryViewer; + } else if (fragment.storyViewer != this) { + otherStoryViewer = fragment.storyViewer; + } + } + if (otherStoryViewer != null && otherStoryViewer.playerHolder != null) { + otherStoryViewer.playerHolder.setSpeed(speed); + } + } + } + public void open(Context context, TL_stories.StoryItem storyItem, PlaceProvider placeProvider) { if (storyItem == null) { return; @@ -340,6 +360,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat doOnAnimationReadyRunnables.clear(); return; } + setSpeed(1f); ATTACH_TO_FRAGMENT = !AndroidUtilities.isTablet() && !fromBottomSheet; USE_SURFACE_VIEW = SharedConfig.useSurfaceInStories && ATTACH_TO_FRAGMENT; messageId = storyItem == null ? 0 : storyItem.messageId; @@ -1334,6 +1355,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat // aspectRatioFrameLayout.addView(surfaceView = new SurfaceView(context)); // } playerHolder.uri = uri; + playerHolder.setSpeed(currentSpeed); currentPlayerScope.player = playerHolder; currentPlayerScope.firstFrameRendered = false; currentPlayerScope.renderView = aspectRatioFrameLayout; @@ -1345,12 +1367,13 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat t = playerSavedPosition; currentPlayerScope.firstFrameRendered = true; } - currentPlayerScope.player.start(isPaused(), uri, t, isInSilentMode); + currentPlayerScope.player.start(isPaused(), uri, t, isInSilentMode, currentSpeed); currentPlayerScope.invalidate(); } } else if (sameUri) { currentPlayerScope = scope; currentPlayerScope.player = playerHolder; + playerHolder.setSpeed(currentSpeed); currentPlayerScope.firstFrameRendered = playerHolder.firstFrameRendered; currentPlayerScope.renderView = aspectRatioFrameLayout; currentPlayerScope.textureView = textureView; @@ -1492,7 +1515,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat playerHolder.uri = uri; playerHolder.document = documents.get(i); FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_LOW); - playerHolder.preparePlayer(uri, isInSilentMode); + playerHolder.preparePlayer(uri, isInSilentMode, currentSpeed); preparedPlayers.add(playerHolder); if (preparedPlayers.size() > 2) { VideoPlayerHolder player = preparedPlayers.remove(0); @@ -2004,7 +2027,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat if (pause) { playerHolder.pause(); } else { - playerHolder.play(); + playerHolder.play(currentSpeed); } } storiesViewPager.enableTouch(!keyboardVisible && !isClosed && !isRecording && !isLongpressed && !isInPinchToZoom && selfStoriesViewsOffset == 0 && !isInTextSelectionMode); 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 25bcae58f..13e77719b 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 @@ -226,6 +226,7 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setItemsBackgroundColor(436207615, false); actionBar.setItemsColor(0xFFFFFFFF, false); + actionBar.setItemsColor(0xFFFFFFFF, true); addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -1172,7 +1173,7 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N super(context); setPadding(dp(onlyPhotos ? 14 : 16), dp(16), dp(8), dp(10)); - if (onlyPhotos) { + if (onlyPhotos && false) { searchButton = new ImageView(context); searchButton.setImageResource(R.drawable.ic_ab_search); searchButton.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); 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 eae8dba76..ce0bfd7e8 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 @@ -469,6 +469,7 @@ public class HintView2 extends View { if (shown) { bounceShow(); } + AndroidUtilities.makeAccessibilityAnnouncement(getText()); shown = true; invalidate(); 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 0de5175dd..580f3a08f 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 @@ -3687,7 +3687,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg return super.dispatchTouchEvent(ev); } }; -// galleryListView.allowSearch(forAddingPart); + galleryListView.allowSearch(false); galleryListView.setOnBackClickListener(() -> { animateGalleryListView(false); lastGallerySelectedAlbum = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java index 98f562c69..5882e89b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java @@ -63,7 +63,7 @@ public class TopicCreateFragment extends BaseFragment { private final static int EDIT_ID = 2; long chatId; long selectedEmojiDocumentId; - int topicId; + long topicId; TextCheckCell2 checkBoxCell; EditTextBoldCursor editTextBoldCursor; @@ -93,7 +93,7 @@ public class TopicCreateFragment extends BaseFragment { @Override public boolean onFragmentCreate() { chatId = arguments.getLong("chat_id"); - topicId = arguments.getInt("topic_id", 0); + topicId = arguments.getLong("topic_id", 0); if (topicId != 0) { topicForEdit = getMessagesController().getTopicsController().findTopic(chatId, topicId); if (topicForEdit == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java index 15420a5b2..4f65541a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java @@ -193,6 +193,7 @@ public class WebviewActivity extends BaseFragment { } else if (type == TYPE_STAT) { actionBar.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false); actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle)); actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png new file mode 100644 index 0000000000000000000000000000000000000000..cc35cd339e940917cbeced17ba7481658ffcfa6b GIT binary patch literal 581 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM`*?LbG$B+ol zx6?Lyu^0-p<%h0WlXK*q!-fqP-8Tr9dhR@bOk;nO^QV2kZnbM0MY7j4FM50OgvqwqeHl|$UxioafJ>3PDY z_(bvZ6OWborwR?`bMAIn^CjU@-52q*e4FMhoFkb1Tq;Xz+5B4HdfvG^57pf?I~m`k z_N!)sZt@}N4XkYEdR8#=tSM0Lz3jybCNCpatXDPVa@xw$<*2Q=bM4V- zM%Q1gt}W@gb#B>ncJ?5>>(&a>U#otIQ+(3FIWzPFvzX`LKR<3%^zA$RCy7%!@ zhn7s>J9gkG`>eKAdvY#^2BfY^>v{_g%m@3mK5(;r=Fwjk9rOwmg`Tc{F6*2UngD$X B>CylI literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png new file mode 100644 index 0000000000000000000000000000000000000000..94e831c6df68ca3dd740b5961f13bc69ce0e9d59 GIT binary patch literal 879 zcmV-#1CacQP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~*-1n}R9Fe^m&{whun-M!V_lSNmAE%@l}ud2SP>FvyPDwU@FXFHJ9+i$g6T}tj2umP+EtHCGm z7Q6t{S(eQ+{yn3K4D1J2!AB4?@k^Y<*ZttZr$KZO+y(WRWfAyoapsAg~}{Q>I6>}L7V!?;ymaPO~y6gFqi=`dxEpGOdks| z1h;}|kg|iCC`mnFHjym)ty+E!N8nIGOx!n2BJ-1A3XFn}HnOi+p~Raizlh)SaBz={a`EnwR1m26<7&OzKFz!nB6U zzAwJ#D*icGQK(lc->i9P>eO3iN3ngISohjoU_J@|A@|8ydS}JWS@ZkM*I8?A+DqMy z?5M=LhGPJv>=FT`J_Qm7E`pQ|m`?nkY`t+r#$leO8u1sdJZ`uk!jqz|-_WXX&TkJz zo~L4LKk@SAPgzmdZ%D2V|H59IqJBfKjHAKhOHdrZe_lKK4I1bpJ0B@ti5rH^*D%qtJ?7I z0b7A)r#L%jHAj%6sq5OK{Q>SmsAy{I%UnZ3+8Qtar=14JHD{D#7g|7>i(1(YlgoX7 zv}nvp@;;@K9Q0=jAEO@OJOrGpPONr~kK{Js|5JDmZifUjZU$$-ICuceh5j@1hhPH8 zy?h%8{^8UV4iShP0CV6r7zMjQR2cvAkY1B-?m#1V;1{T^3{)(Gi`)PJ002ovPDHLk FV1fxMeVYIP literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab075e9cf67275bae18f49190e3439e8fc5ef27 GIT binary patch literal 804 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM315=-;i(^Ox z=i6xqy+s2>j>+~KF^dc7wJcH*T5am=ymu+ ztK%*$mZ=$mEIYdtrfhKa5ORF=y8O}Eg6C%}-=D44zqjaKYk&E<^8KIZT9-dNJ9pW# zV;OG_*l%MFv|YbEK;zAl`+*l2r!CU>6?Xogr@q)G<~ywM4mNheUsM)(F?W4$2>c*p z!*=|0#e&yN-3O$KD{YLV=IAwrKK;>MqoK^l@yz-ld+74Z&W@fxC%l?{OYuZ}HDAW8 zgR320w<^zbZ#({Q*7Kkz=EknBO+SOgg>K#ZWD{f~YWpBP;^mRuL9Hq;ZXMjU`1+TE zi2E{XT5_uAO@e3TerkH8GF9y@TYjLvuF=s#PQf3m^pBpH9^87A<*vJPc3^(V-tErr z0`IOSDc3Kz-1Y5{?3F!}`!nxFUog}y`4rh~pIRVhdU|$MkbedDt4mJG_nT&$RanZM z;}gH6`-lu;gxhw*Ftz9_cx3$q9Tm9MTiwnXXlE-;~XIEp++I%B{1M)VFWkJgHUX zykksDV@=i{hWQ6XcJMw)ecl_S@A%W`%x9?&d;ZJxOx8Id^ZmlZnQR`tdEOno4bdf0~Jk|Y)yd~ea?AWW8Y4_Tv zn%sFVX?&e4YR}JAl|I%DUkksk$hsWG9eF_^g85^G(}k$j`MzH_F%&R;xtelCBk#?D d|NEHtGxDoNZ8vE7@fMUqJzf1=);T3K0RTYYP9y*T literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png new file mode 100644 index 0000000000000000000000000000000000000000..537a056d90b6efc5bfc2fe34d72f7fdc11742562 GIT binary patch literal 899 zcmV-}1AP36P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~?MXyIR9Fe^m&2#HEW4|+2A zK*3~%_&NwNy8b>hGuzwgp3Kaei)_KSUG;TUO-*-C&1_RsLmDgapRGVH>-|(Jl?BAM zfg)H97K1Vv2Tyak+!*8B3x#xo8{i9wljlsH2FvH9DiXJYA&^$S5pWjd|4Csa%7LR` z64WCj1aGLjD3bKoQ-u{<#@>{4u;BXME0Bb=nP!XoQ!B~^JD1utS6i6x) zI2P>-!L@+zR+8(sUub(DdlEdvX-DW7jFXI)!F!9BIl`lUM+&js8nN#N_BqBA(hcck z{=Q-RRT6Ho?kF?|{87_0I5vad0h-04_W)aNyKgrm6?zH$1iOIQS59K@qmX-y3&BpX5%?tTI@K5wjschSK}I)$J|AdR zvdZD=Rbw==KXF{41m|oM@PiKjBve;S8PzE=op)qAA`kdH(4iOd)u@>o^9Aq%xa0@q z(wR{X2FLA=3_Ws%FM^sr<46%v_zpO7iMkm%8A@~>3{D+ZTlN61!{E1}-(v19b9=<2 zztf1lmq8zE5_4PiwEBA5#lPN3f4In2V19Dwebi#d!)e7ngEVr*&XdUI3ieqVhwBA; zlk1Is2QLNC(rPiU`#E(f)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~zez+vR9Fe^n7?ZjQ4q)PPEq_3 zi8e~qQc{S8g@uAhB8PQKQ4~ZAOAE2E2o@;>QA|J~So;@P1&Pt-0zrg`ML@!L4^f2EIG*&3E3L@6Fr0+q+6-!~U}lR6V^>6zzl`@NzojzE-Q% zZyl{c#2~m2RzMjh`^x@*1nND`Uz| zYG9G}y)m*(uXPr+hSjf_puI}GE>lFt-d4}*$AUI#^3RM#WrnPt)vs*!s&Tfb;V*%4 zTKqQ5g*(Lj7I*|VD;%*axDj9lJ~NhEV1}G`_(F39vHChV14PU?2<;-1vtT!vRe{rC zLNH#1zk#T!AeK3_dnl76xLpbJVV=cyXz*Y_N|#Q6b6^h0XWJyAPT^fE667v+$OXF5 z0FTL$W1rVt`LK1ZEJ1NmMEzm%Km*6EdsBNuY$53YSk6ms zSCHH%cF)*e@%Nww953HlX6bz_-t=z!g3LR#z7_)RUceU(r7L0)crSxIYgbU-`gY@E znz+o1`r$2V_sG0GayjlhdAnZ*7c}W^Zn6?Zf~3V_=3BGY)nf8468qkA&Fd0kj2|{x=VHluDKik#;<=23XUa*A*aCP8euMpB2z&w0!8I_#ajoH9b34Qa6TH&f z_+RN=h&_QDFb*$5>gl{r=hh+FOl)h*C08q$M3RxmC0Xvs>RJ8xd_U>3BkuC{MD_HibbMs7qF{iy-v8MU f=-C+dWe5HOGKsxnV3OQ`00000NkvXXu0mjfe;{>} literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png new file mode 100644 index 0000000000000000000000000000000000000000..a7a8312bddfbf4cfe46f7b84cfe8a9a6a6391317 GIT binary patch literal 876 zcmV-y1C#uTP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~)=5M`R9Fe^n7eBgK@`UCy}s}f z4QUh~osuF5T3U$Q$o&KC#YzQ13rn#QOd*IO2$IT5iH((@h~T4%5JWIo1S}*-(85C0 z_=vjxKJT2}$!7L-T`nj&@ZEFfJLk-totfR8y^Y4Q{9`lF%&Rwwq7C>5@?rwM@6BfO zeSq(cqKH9o1z7Dqed_V1Y$tY%+fuDo5;4K&flVA>1k-uLu zifMsKAbAFcs#H*WECr0J5@Z34)ILCk4qGmEztb_LbIr#!VWS5rYPjI zd=#aJ?^U43$u#^abf)C)q0Fob4ho0}e+mwO;}jT=iM>x4qKAb8&mDP z<}2r1jouDsUHd5d5YX%Cq`0yLX`k4hQJy4z4|bcmzh6AB-_I(?n{LF@=Ou*9i%fmX z2SJxZff<};MWW??B=E4_gJk?sZV4!!~Np;bsH9apt&Go;QWYq~1=wE+_* zvGROLRIX*?+4%ALzH@22bJOd0+ITv{C&JYC{RqpLBS1%HNjs?q3!<-we8w9B`k0XD z&Yhjb;5`%)oE1R8U5!F2dUY0000gv literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png new file mode 100644 index 0000000000000000000000000000000000000000..66c6ce2bd1aba5c1baf1d81e881941b88ba89cf7 GIT binary patch literal 993 zcmV<710MW|P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0OG!jQR9Fe^n8|BXQ51*ss^CDy zI)EaI+JzMdtO#Nir(#7M5L}5X#f?y0xD&*se?S)s1yK-66$(PJir9qyT?66RB+ z?UUzu14Z>Ai7IG_vKo|5wsbmfV z)xj~C4PRg-%h-p`3dvMJ7f9~F^sKe?C5`Xmpwe+GhDD*VUKV5!mJTz--EV2FeGDuT%j%f zbm*1MAUQ8E_E3!Zz3ll6e`GXhE-mt#BMZ!#X$% zkrKLOJe8*3He6HA2|R=CE;c1*C&hxj#_yJ^T*I%MatCapyaijQIR@#_8KSdpZ0!Td zQ3hO|DKcfA*A0#E&f0=B_RF*`W++5!GokMk|0o;pKy zAqQ)ZOo%6J!g&?6!w*;p2jCKPl9Wzel;}H4GC89Pe?}&xt|Zk1yD3hCouFhS^`N63 zC3Bs_vna>Vgm`*=>1t_aY9NvtfDYJ2Rc`{46&V%$Nng#V?lDPUMiu@HO^9x5L9=n2 zfmhowlqXQOV{ZGy%)Z8NF_rV6yXqBOfKUlN_Vj!J8fZS;B!G^vPE{Rf`QF1hkm$aV z9KvreTCcuS)qrRZ9cE^2FQprUK0;@R0Y1=4ms%^xSF^Mol+1N#z~?zyavF3^RD$-5 zHt-`*-&*`Gq9Y}0hO}>9Fv>ojdOx}v^hTMa{Uh2J>TOiSABiRO(~Y9N5hw)wj^S~j zarBKA&*J;9A8*~5{!Kjk7)AB8cv|YLupH%nh25OZh7t+=GcWm`WkymplzTv%R#RBM zpFspq3rUszhoa@;YmzGKPicS2{ETu6B&SPGH*Tq<_&*y;6?tr&xMtuN$h1vfjOMXI P00000NkvXXu0mjfETgHj literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..90ea3da0a0d066101d46eb17581cab093b10c2f7 GIT binary patch literal 1031 zcmV+i1o-=jP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0aY;l$R9Fe^mtSa&aTv$X*=9F{ zP?A5jQc4sO(^g9>OD=YSTB7DpOJ)d5Q7DPHapS@g7rS%AgHOcGL=45``=A@4#tr7&dcvomj0@D`vC&m{>@j zHS!971zK9Q!eFv;%fep`KSSXcY_eEVOYL!qI9!WePr*8P!V2(f;2;!!!c7)SYN@?0 z5r?g@>PbH23XWO<*LCo#8~=fAv{({L-7NUd>3qV@FIZ2~Nmrn!!v|ya@SBTipW5ID z6F91K8Zvib-rukS*pfVHBSQou8&VcIjZnWOLBFlKP{EJ@HPuj0uJ8y}=1nC~upt$aw-M^8 z6TZNje1eSELOm$8*>T2BLBrYXxOYu7RzpfAw+Y%^YQL%uigMisgJ{c&R}g&Y613vE zPaT7?8*)u;qvp30)uXH(-UI$sH*V&w#mo}W=4;rl@iGe*W8HDGi&||HI%aO8zT9c) zFuv*hIA+vV;}sy5XoYMR>RO-2u1mWy`pOXw zlOBVH*Em&{j(^w!*s&cQCK|^wng8|Uzk~}^hn)huV64N{UO&js%!xB`R1O-aCFJlN zJ1@}G?5J8VMuA??4EqWe#7IEwya{5T!T2{y@+9~K3Ob{bygP@sht35FIy}XOu1?Mi z63MGjegN(Lx*xw6=I*2nMqr585q9$)<)C{JvqwI74A&C-;9V8^pjaw}$C1TX%E&uZupZf33*unOLX6Zn5u;16K#vY^?vkZ%A0002ovPDHLkV1i^A Bz9Rqt literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..cd79e07874d37c49687ed0b4b90a24025d11a04c GIT binary patch literal 918 zcmV;H18Mw;P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz007*naR9Fe^mpf<_Q51%EV>D_I zf{%boihxbfLM(ism4z09R!J2QlRAP5f)*lJXk{-5Mzm27v9Pf40g5PC7!*Nb5mAy9 zqJ}7F6xZ(`?-|cdcCxcOyAdP@e$Kh)`RC5Pli5O{1}T+FonR+eUPD=PQX$a`z5>Y@ z=xNTR3|$%C2YvuAlPu<+6hlSkXJ8@{$AOWXUs4SAI};DD;P1|`(fLvmLw~Wp3zk~f zMEt7!_y$AX1GI1-+yFbY<1&%4;ndv(CjI8GsL9$7Qpu=@xXz4!OjUQr52JRqtN)DM z<>O^G!FNCsUu~a&KNlJ6MW1~d667AbXt7x1TxJ>QLvbJ&_!>gS`qJ-$n|IXwu_oBz z63QL}{)Up#PiI6ZBf=*4ib_eG+^F#4m|J0plr3_?J>@>Tv%0 zx*k~>DVlVHhu}n6pw0z-vL5QQ6-S5&kmwvWP3WI`?OPI4+rs+qdm)jKcL|wxdRzgE zfd24)&af^~BuPT%Z>By^^9^CZNyxlR9R~Z;Ad=Li903|v|L5xaQ=qr1iGPRqw7P7X zt^xM>GWX|)O`u?pu|Xd;e8Wd z&@GTmfKgEIn^Xtber>$P-oioth|VsM+6(-z1(vxb)6bw;J7lyO-+?^{c7RnNHJ4bL sXjioxkHAHCW;!i#!N0Hr|LqR^1|)gR=p4s2z5oCK07*qoM6N<$f}Q|}ng9R* literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad3859802abb8f4a35d4f41d11ced1630a18c9b GIT binary patch literal 921 zcmV;K17`e*P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz014%?dR9Fe^mrsaIaTLejW0w{pS%d0C8OoDMRBwQ^7 zJz_0j28i7b5?uj~oLaG2&e`o%iLA*0qGYJ#)h@P?H~?kE@o4`T3% zoZ5SWrP>$tklMgU*ENk_8zqxl0lqoTSA1ub6I#PP?fS%xgm_*a;x-_sLF_4LvIN$* zq~L6it)+?Sv;943dU7;f(jD=oQ%Brw^4C*|MM(5_fG>9+KQ3mlo zlV7j-YCRgejm~}Id{kqBO>kTOw(CIrCy-A}qkjj|RY&Z`ACES91I0}oZK%Wg1RC$0 z&IR^dXEnWnY$2dV8KyOjPl8su? zN--T1rLMVPBFZP-WjIHq?wvAi;E-M+mWlU*o8So;1cyOZCYOtEOe;T>+rdh|QvC{z zq*JyCPUTYu;Q$bOQ~e0#9q7bf)WW28UN&;37q~A%v2;QEmHMvOXEXTghIx*UzwPV0 zZM+(r%M0N(ATM+B%h1C$JA*G;>_x4`jQnME*EsD{4D&L$57TFQ%Fs{zarK6yL7u8= zHQ#Ag9MMjo&$iUBA3Jm!{4pz7YmDB1y`agn;guUozR~2tShJyHUtw=l5-fW`qInYy z4}pHtd?tPi%AcepQW-UhS~}2*8Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~ph-kQR9Fe^m%D2eQ542!M8OBd zAQsv#DFj6{g+qU1-VhI1jzMjY&MQzKad}}0p2E76m3BG z#@VX*fPKiGOXy8<7U8&`mm5Q@#d{|&$&1~Ca8b_{W@sM2x<-ob+1Q2JHDI;#g#{H7AYF6Bo9MYv zslC@wtPP)byDGm z=wq}Y`I?Ydkn}yGm!9pL=XkIlKKX&fwz)$urGgb5a5S=ptf#RXD(atsO6{^OX^25G z&mnt%MPI0~IL+w(dJMGab+74u8_1S7#K^k84!aJP-TgLbXvnblgPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz06iGxuR9Fe^m&3)VBhKP`@-{T=6qETVSTMs$&O-1~$;c?st058hmRVm^lenH>ry&d*y$OF;G$|0^)_ucm zZ{14l{uGU(RaXd3ACQcL6~Ml?Zlnqt2b@(xD31REu(HeJ;LU7^cq@2ovXcg|Pnq#A zbZSz3112st;7!N?-y-lvLFBO)$5E}Jok?2dvRlcRtAU!4oOBB^*2+wmP}2t;(wbWK zP`8Lr`HZF+&oxZC)jqEnj_-$tOb&UPl)%B_5eoe1`*wOtKw z2jd>&yA1D+8`lO6-ZK0ffR$b^$qWeUKkBm~T?uhqAH2F=j5@|jbQBF98~AnlkGdoh z(os>F*V9DT8b&YqUs7zkj;)a16=%TSRFdN$F5cN3ye>F;FeF!<623_=_wmEe%s*ld z_xLf!IP>^nm(4C^{+aSK`=GWP`Y~?Rr)VnO&h!zslR4}=>squC8-QE{_VZ`f4*A|| zn}$j>Xg^VA_cO>@DSar~V+Cfzr1lR*r>P?L|M4kpn`-Lj3gldYzxXU6d9rey!~g&Q M07*qoM6N<$g0Yg4V*mgE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png new file mode 100644 index 0000000000000000000000000000000000000000..9957f98715d446e80c22fecf0acaddc51bd06e2d GIT binary patch literal 867 zcmV-p1DyPcP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~%}GQ-R9Fe^mb+^eK@`SwuK__3 zL=9pTgN-(}B7%wrd=(FW@eZ`&>NIVq(;32Y7u*Ox!|7J5^%}Wypolgc zfm5&wT9>}P>{XFu5Kh7r$ZjyTsO&8Z!6!+u%_SLQEPjFma5xb07w`Dp%Qnu0c{74y zv`xMZXW@4CJaipp{f{LlOFn_Moia;B)C7om7OUj!bhDlOcnLD z=R_Q`sK|Rcfn@J|bwzYV&YtR?G3Ws2z}x#cr5HH{>C!XkY081O_i;)wathK7Y|x{f z18?u+lw#x*H0`{H-8g0F?R}gS-|jXX%zx)8Q<)T0=N@|Np0LL6p*F#DZt9P&m`99z z9+8!Lm#M)o;Q`)fA2ewc{L`Gb{jBTKQ^s2wEyjYW{V?TwXe)Lq#1Jhid&{gKFUb`B zVnna5j6=Jn_2?g7mhJO}#l|WM_Uu%tLpZG^@CCRJu8SmjkM2Ia#XtQOv71+AcS^;; zCol&S7)QU0<||@=ZLw1iy?#-LFusKHN-%haj6I^;(eDVhcabOP)LfWHg^I$!&eTuF zoA8}2Ibk>o1s%F5uvrCf%Q)a_)S;lnX8>M?#|o;2DN40pm{?ftKEiGdd@P56lijV; zG(E3!ABLp;@DBU}Ptj(z`waXR?5=zJC67rG?GXB%&@gHVS-5D6$j!E1M`m@11h1eD z@K<;P8uo{Q4)u3iT(acfMLSfLpwOM0RW`NP2tE#l2Pr|YI|AqA0A9fLDSk1V{(@4U z2#4Svf}cai?jhYl*Pymthx;^#+zvO>20#%9;cu7&b?9sZ>8nE!{5<@TSkVl2$EzdN tTV3?(un;6!&3HGAzFgU&=jPLt`~#?|tPWo0e;WV*002ovPDHLkV1l|}db0ok literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png new file mode 100644 index 0000000000000000000000000000000000000000..076ee4d382dd37b5ad47eea5bf10c320bc32883f GIT binary patch literal 802 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM315=Nui(^Ox z=i6z986l1WZN*YOZq|-2TMRgxS`!pGxZ0;idAe-qV9^$Q%hWZu*Hz2=EsLO`D~IFk zh6v3jv#z!kES=&$J}#{ify_zg-uLf5e*0wg_jhq}vmWu*m|Jf)-u(I7y?3$R-ik;0 zM65S>l`n`|yX|ml1#fcRo|pT#oPK2cL2k{NM;6@K|2>m+w(!e2&&s&YmzKHeiignA z?Lyc2mmhrg=YToe;=bvZmIl2Pwu)ak(QF6HXN8%~i5GSk%j`<<-5YxO+3Tll#UiiT zwk!PPd!868AYwQpyY+5?(7FS$Ga6ifFg;g#*vs#E<>f`aii_{2EEe6c{b1k@j_nUD zbsT1WaeZxKvg}c9@YfCgN7f53QJxoCH@V`_b?>Vz)6aVO*9!fsGoF6+kLM%C`0eY| zHk@Bma!d4jkF8>;@Ru_;k6$pm)?${Lr&iUnY}*Z;-6w2?Kb*cP z-Lqe^c;W-`4`)?M6XMPHeOS5kj2eeT7t2ehDQEtK&a~?fDA%7kH^5M|WIF3?Aql-7 zOjQSazgw)mZQdP{@vKqk?pfQMu9^euW!IeC)W)&Gp!%xokG8l(_Rc&z-`sTeFIQhA zykIZi@3|xSO~vFVy#~DfH7t({Pbe9y#5SuNp4_N@cD-cAr0T?T){^{3MPfQ%FI+Es z_4K|?C!XXU%a15*|NQd0jsH%;aGi~c_f+qCraLTmo|NwV`HFPRsw}&xUfCHYrl6@p*N`zV=eh+4I6LZ`@yFIZNJWk`Y7uim!T_cmK)y zc13^sobr~(Z9$BBfO>FzK7;Rzy`EE-Nd=kC%5whdWWJ_7^1`ECXTQc*am9LUWIoEb c=9cUaW@hoeb8l03hk(+jr>mdKI;Vst0EG@#0{{R3 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png new file mode 100644 index 0000000000000000000000000000000000000000..742dbd18e2fcf2633942e05f510d68acfe99725e GIT binary patch literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfOxDxIF~o!S z?UaptjE(|r?_HLLbOb%+G%!w~-WyI&o-ED0Q90uI%c6XT#-69Iw3a-SsN+frQJ;RS zU>|Rf+SXUk&eXbnny0X|TKdG+x2uKA8)w{kkoiNmvGeWL9AT|#`Z{47cT`_^{3QCQ z{FM2HwbCg^OzfPww&+euSm62ix7h~&{H!-yvxKd_*?!_p^zAOLx!7?nbDwn1ijIl{ zva3HAw@!a1YryXJ``P+KR~`KJJ>QzJU^##G$C2!+9X+NX%VwcO5F90_DtNVna0(vK{_^OX_~7eeIhqZ&=8K! z%E$bi|*l23X=@@j=`+O99QY~T0x=gfvbH|3o@d=9uf95gDl zEK&8p*PttE@MWfyLjQtEl|3_xcyxJB7d$x{Z#(zV zNKd%o6LIc!AlFw$&6>y`yq?8R-!(trS5OfCe)gTroSHj_j_kee=5*=9{@7Vxn}4e1 zv+*k0ahNYS-MMuq*CfsJ1)GaJ6R)zL-|w2maLcy#?E33d=K8O$mXA2XcWvw2=^MFc zrMaw literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png new file mode 100644 index 0000000000000000000000000000000000000000..5c767c0b164ab7f748dabc5e3218fbe8f73e3d16 GIT binary patch literal 578 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfY>lUjV~7Xu z+bOo*%#H$W#Rq>dYH^9hr6%Sls*82rxY5~~pvd^&nWw|v;jL0fE5|I#@&mFfmo_IbIw0A{4v$tV*{`D5;Lx^ zEWJzO4%VLhr#>UiHHjSwdsfFH*Q&dReP4* zBe@x^r6*=PPWsJ|{mCfj*zUzMPlQQ*(>VRQf_ZvPX?cCq3MwuZf{yB%y{@|=-d}ew%@*dk@pYdzkKe%iye~}c4maQuv+IH_1Yld=#eZaUA=LGpmltGquYkyH92dXt+sC5u(5Yh zldFjk%lsb-kCdE?tSi)Je>9uY-4#`q zBl&YmP%-y<53?xYJ4`H!2J<`eAC=BvtmM<0`R8-u_IcZ67QOR|waNPa#67on4;#mG zn^`-S)_deRE)TbV9(=JWU|tvBg@-I*jyXJ43pwX0@VeV@%UAes)>Y6dQ@$RsF2C=j g{-o8n_t!PrbKc)tHu>IdB~bi&y85}Sb4q9e0NT3mwg3PC literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png new file mode 100644 index 0000000000000000000000000000000000000000..79d0ad341731d711f7790e710e850b58c97f36cd GIT binary patch literal 625 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgf?6#+iV~7Xu z)v31L%#H$WlO+NApgG~McOkv6@d$x#-V^VVhK#x24*IZ7T@j(-^cF>*UP_9QHH zz2FqE##L!i?~l+Qg?9Nx;`%#PXUq_htS~Az-fX;k=Uvu()>AJ>o?$!o*!D1T)~ za{Y$jCn|sI{_i!M{wUDnVEvQH2Mt%0&SFV@(6ONGfk@f|p?wP_GSw^jroDC4zIo8Z z*>;mMZT&u6@vRrgA!{;@s&n}c~-#zHo$tG5`0Zn`Ck zo;h5l7Lo3yaV25$!P`~p;wX9~;3*}x`uW0>p z^0G#Gp{=*iKA$6>S9|+^sx~&*eJZvr%e9%K=73?3qxKe&PQ9HLHI6=|#VqL}r#>Ex vT?dpKj(Ft+|v@V@$!a)DJ!SkRk7YEWL@8|msd4gGrFFE+jXTNx7g&TCuYr> z6jY}#asIjWUhB_$;?J6x&G}Vw&i478;(K!~zweEBv%dSOT|@5ewQJlH1*Gm6_Q$5| zO^>|Rd|ZCtk_tAifVF4Z!&kdVr3M-H-fHKb(QH%WI76iJ*YXVu&igm(#5i~BN33sN zR9Mk?wJMwSZU5t(b{3H)p;up59^`+h!fDYqg)@QQ((b66%x{^yX+?*&tY_?GHegL& z=PSkZQ)G7G8|5u-RzXctE_n(W@6NGJE;*&yrpT|Ird&3C<6k@X_V$wbFHT-xc=C$r^?h5^7I252 nRloeEJp1o6%YXL1x9lh7-w!DjYd>oq4~k|_S3j3^P6N literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png new file mode 100644 index 0000000000000000000000000000000000000000..425129fa9b12716c91695b4334ae849f5acd3899 GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgf?3t&FV~7Xu z)v2eoT?0kh-+!IfXrr`V!plv`IB3QPb_own&826SEb%#^+&|IB(By!ugvJybr&BH( z$x6aX%>A!_$NrA_erNa9uR8mGMZI3L^?OwM`_1Pq<<8enH!oqV+iySfwUI{KjSDd% z|16Wg?TvfCv{dJ)^aGiFi`CWm9rj#S@#AYOI-~T)L0IM>ca57RPhP8>@k(=xnQYkw zOr8fHh|6a6G=)u))o2uEF2C^q=&W^_S2P({26jq#w2EAC{>2$PLuu!xECIz`>Q3Sr zug@ijeKHle%^1Cb*ZTr5r=Y9Pfm;nR@;-;ud>l-D8n1A^+>rCe;2L|`MO)q_W$7&Y z_)Ail%^S`(c|F~DTtKJ8o@LVH@~giySU+F6wDIyusfp*gw{&mKJj&vo>zU2mb=EMV zd<(m7fyd&)HNM-`GHf4RV-wL%y2RK!Ya{D|wyGUgxer$vHg5jVvW_`_ld7S!&u_c7 zt6HBP9BlZQGHLbEYtGVh4r#e`HLh!4BzQ#2fj_varF4by&dfjJ6V@d#a?L&U<6V^? zWBQY5<-056j;s)k^N%iJ{w`4Q*-85&&pPMzi@%iqTJl|=Ikx_N^71ef4feNR*+LxI zGW6}6?TUU)vOC=HYM0B0<#iU#SGfKa{ChY3Wz@O)T@|eVy%n=d#Wz Gp$Py-4fmk{ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..28c4aaad02a756f5c635612d76e2153c07001b18 GIT binary patch literal 695 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfl1NR#WBQ# z_vlo6kI+Dw8Ev&&G2%flbs14XS;xYo2^BQ z*KPG}k8I2x7;7XAcrS6d)UxmA|7c~=>R-6i;t|^n#hFK*IY>1T_(b zWY>Amz4m;)g%i7mhYt6>W)lW0j-Ma+RqnFJ->}@k9sk5*$J5P1#~;4A|GIKEX3lUw+^_I8t|RuZGP`ud>|?AS zB83C`CD*+FBCFKDQg2qt%J)ujifdLg>@{${wLw`wYP-=z=HE+Bh81-uIJ>^6jHvtI zb6+u0xXwwuruD|zWBWAbu8|L5SiNBPhnCA|75B&XU@!7eF@)h z@U01Ez40}GwXkq@df3|l@hnEK1l})dvu>Q^$<8`@cxvOnHBv#hf12(7%bqI|U!@jO QTMbGyp00i_>zopr0KcgakpKVy literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..aaca45a7b5ea6d25b940ac118abaedcc47070dcf GIT binary patch literal 628 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgf?4GBKV~7Xu z+bMg!m;(jeHcvXF)XL%_a71On0)Y(^I(ip{*)=Le&B)Mgy7rM*=ZMn{DWGg%? zF#TtJLkEBMotGy)g*O(b`{fC@Ynj-%d@~Z;yL0^xuApk3q|DyPc?~uy8#8@3@TurM zx46t~bWXfu^)!_fo1~Rhi3x?G&dFj=rtWLe(>|xfo8&qna{HW}z6Gtnm^Z{d|HWE< zqkC<3v&L-Y69-w}IQh8#u`%Tg*nQQC>25%Sc4sT^VU5Srw>&s+BOAOyYzgDnweCxr zMCKn@{?7X2oO1gVQKd?*W$&7+`l|LVOPn1LdQGJ4V@%eziruGex!4sB|7?0Ka41q> zc8O{qp{3w+LAnZtqD)QsqWc+F-0&=amCNNb^GfZx4G<` y|5Zliz|`xzc1@4hsNW=GUSIU&-}bk@54ata+gBaDc5ntL#ywsAT-G@yGywntqVqlg literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..515dcdc98808697f142bbafefe8ab4f1b753de8d GIT binary patch literal 628 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgf?4GBKV~7Xu z+o}E5%yX(#zp{Ea?yl4|zDzhYJj?B{o2aleW zdz#QKl$)tswDIxhV`tvvm)C86JAd-0SDQaS`+e{C-uv&(_s=x#vCp5Ddi8)}P1CtJ zLGe?uD?C4P9Gzak+dm<{nL{^#|E>X}T1R97|MO*;`#K&NOYvA-zIU2`(e;C}OB~cT zGh0orsIS{w>+is&KW9~;DQE8Oi_=|?uW#b`qT%y!`9sNBSF6seUtrvHebSXDJZ3HP z8?`wqPfE4#FcGxA+ETCD)Lqt<>f6<{|K*+UtYVssMg4RCSh|{BnfX$FQsR;;O-yxj zX2=NLyryUFpZg#yHP+HKlPmcGgS*K|S?Pt>Ba@o4c~m^t^fIj#oZZU&VVht*_mOEe zt{vGQ6a$Yx>DZNSr!H^%My+sa`9ZTkQ65fCEpt*goZ;OPHltBg!fo>Ol|_q_WzKm? zcK&&^z2k}Sii~Yj`kVgURSXDZekJ{o@!kRJWmiv4tLgSPII=HYWN$?I^do*VmfOA5 zPI^!(FnN8trJLT_0QL%rAPd@us{Y&--UppmW>-eut(hBe3|oy+sW$SDXq{A0@mDu zTRA$mEfRFxvf;wlI~yjyIi3>P%w=cs=1lGTb1BCwv$eiXf4J-2oF7|lBmczwdBQgH zLek%bmD#731@l~6aDGy~%WCVs%Nw2qNxt_G+xw(rUWRDC-eb+jr8hpB+7cEwi zf4I6KY4_^xl-Ls84$lXtotW<_v;$e#Uz?E7-4a-#l@xW4*xM{S&=*E9h&Sy2d4>{((vOT9bre|GG7c zr1Y}Q#ZR(MI=&#gjN$wQl`oz58Lm#>lb!W_<4L1ChsvG*b1u(az3u*i`AaH#eolz* jmNfr)mEZ7Z{k&gHmoirV7Cxvj5fs6mu6{1-oD!M*Ec)=ReH;p<>DITxYsJG?I}s@`D{Rc<;dwb>^Yb(<)98(Yi_|{M^PM$^ zDW>V)v(n4)ZHDV5axboXD7GtRuGT5(^U zKgS(!lNJ4M`)1M_FFtF_iMXDQE7UGcwAH`u6JM(TUJ@?;N#&NZw4)z8fPn)c@> YTf_DFQk-``*n^_g)78&qol`;+02m(fWdHyG literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png new file mode 100644 index 0000000000000000000000000000000000000000..865782ccaf1aaefac40d1e15600cb2b495f1944d GIT binary patch literal 668 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfr-u2#WBQ# zck5JNZI?iaJ6;XkPhR=)_jvJo>*wbTuOABDZ~5Hj{Qv)Vs^8rv)yh*T(Led)ACu;x%n;u)_*-!=WP7SBl1wxEmnGG;RV$xYLBl8uQk+b zek5#`c<;ghD-wzf58XLs=qByr4L^6}+@0zPT{0I1?lkCsv6LvNYWL2{U2uAd z1rOIlK96@3=d|&1Y|l6pcg(e-L9p!e5ee?97jkc!{Fd;~)w^FFaOLbN*6i{n+c>(E zIsDID&Gg-CIZeG%cMlwOR7Av3obLm=VyT0Vn&jkn0HopR;3{O`-mvv4FO#t}b6)OM$ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e3b0d5419c48722db0a56f1419f030e6db472b GIT binary patch literal 554 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfY>KCgV~7Xu z+bMhXodZP<{O(%jAt4~R_+*q?vx|}tcXOyxtZv8A14(A3M^z?v^q#D5XmM1wOJ3pV z!r^>*!nM!VMR9k(|GM;hmV`&ur1F3*z$$A_5{&TIh(wHmk z8l-Y^_m1mN_`YnoWzT(~$e$&AVZW@&;-$K|pBxWyizuu=srqH%tvc6-Y7_ho literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png new file mode 100644 index 0000000000000000000000000000000000000000..a58df3b3fecf7a2a3993cec85e5cbb31d4d3cb93 GIT binary patch literal 700 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~ySip>6gB0F2&*5QUU{dpRaSX{| zeLG{nzKf&4@%JuGM?|Nnlz6F%>i%Ql6ZQI|F68v$ukedGUMu&w6`$HIrg$!W(srZB z>i1>$`<36Q+<)_C&&-?e&&>Y5CwQexr)&oj{IOql#WT&lx8L>&+4Da;5HRWW+^?&m z)^3|z%er6cmy|&L^gW3=0+)+ob&j&Fw0glX-6qL|)swMYPyO__Gj&!|-dtByY?KK( z{$I%FOULVP8x``+Hwc`qV5wMvBrF9`rASi`Y&*q zWwuO9u(P`1y}W@n;mH;46GcitE~sp{=6ibUd$ZFVCz-QdtmIXk<~1mbsw|!nxk+R} z@|PK3R39qTJ6!O+e?WxYSM8|oe^v3yd6OUSnaLjH5cy>3k4xMi6#g%I*K}>_P6tt^ z+XqgBMPrLMD?)JYM*$Wu+4(_Pk`@y!oMdZSf`zOplxlYioZaJrLlf~NAW`nDU z&VAE+am za5CCCuDZxvui>BL;cMPYDxK>1JMJ+C|JhrSsvEA6#4Muw`st=^n-0fyWrzo~J~`oI zSJ6@;D`Ru$-k)eylj$}aj6U--OG^9NyxPc&4C|LL&u4eOx}?bLjTPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NF&q+ie5nOlgBQ546|aT`sH zF=B+K_i;XR%31Yquf5k=|Gn1!_SxU%BoZYlt-$}i0?9baPo+}j@XiI* zU^W;6{a_%OOn#&-E+OGrU@JHe`azU@!*~N61WU%X5)!Bb?cgWKS6&df9ZdXZ#V}bd zxB?0(osdZ(v25$i;xNG>Fb3k1%Mj1ZOjsxd(n@eCuBHyIIgWbZIQ5&kLQ~bbC#fAp-=OF&>L5-h6~}kzo0Wc`%42mP@_79i$PLa_ zG-PvpS)rzf+|&Z6V*A#$j&veJZJ|PFxD#1Hk7c zCo8`~6wu+Cu*r`ih8dTw z3dn0etE4gOy()iB0c?p6IH<>+>R$|cx0*yw0cqnk)v1W|5pubw<`Y&xtLjuldOJJh ztC~+(0atO#=UGMNjzhnolNt-4O8E_((49?v?wV6fiE9CkHlhOB<#S{$$#=MLx)!j;h3qeVD!P#9q!E(O0r zHmdB?N5JPRn@-ikz+T{Vf_Ya3u^f>mk?)%;gphU)*agIQ1Vo7x`v4pTD}n1SFys literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d45b776b3ee537167d6728e1f98158f75a9d07c GIT binary patch literal 1078 zcmV-61j+k}P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFph-kQRA>e5m|tj(aTv$X{*cz1 zRw%>#NmA0vQexH!5h<=vLb(ub3>R|28d=ctuAGQ+olRlUcfaYCuF$G)D5~{ zQQk`8MKjqkUhLpf=(WHfam6TH-ecc;0Ti2o*bPNcb5GZZjQe=mGr;*XGF#Oo41r2B z(J>x}tD)G48H1kOTB7HDN*TG*cmtZR41db^3p9}s)4b^S+nUc5UdJ)Ec}aa>YhDQ7 z1+0;vNPFmr-|XNtY82v>M*1!w_RlMI?rFvFH#<0uYGd}_X{6K7J=+Ol>FEfJXxOPo`_-+dU-P2en!j^5Tg5$xVd(fKraGML8!?dX=#Wwapm9`(0+|U zxMd+)&KN}Qf>7%;#Yn6GZQv@%YY5+*4EK{`)_OT{Zbi&G>KLI-U?8jPIj%K@h?mB* z_J@-TAn!4XZ#FmsWVh?vhL~mCV-W;>!1>%z}w5%_sHwxE+ec%@8 z12U_hzwxdYhmiE8qBV{9A|Nm8tAXr^f{pk?Ak;Pl z3tIxMiv*QrG3o)?=djGC>@XjLF7SxeQI>ek>NUdf%eMQi;VXPdvyGnVljnCksIyhW zf7+8TwEPe9UJ-42(LRKCN`(Mxw~3S2pd-c^&BDj**Q zN^2Co4qSGkv>ioOqw|G8`(`Qobame!S*m#9G%1f$*)rr>2ZN}Et#};5Gmy+cG6TsBlynCE0hN6tHk3Tb761SM07*qoM6N<$f*W(_k^lez literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png new file mode 100644 index 0000000000000000000000000000000000000000..51b04bea0d5f24f592032620fa78a7d788031a22 GIT binary patch literal 1147 zcmV->1cdvEP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFe5m`zAkK@`V*ncq|t zm6io%v?_Gb2c#L1x`?P&)~;m<_64n~UA1sio1o}}T1G8`APX_jjUgE%MUtR>DP@^y zfqh76zhmz{?i=sincIEO3hseFGv~}X|2cEs+?jh{Mn)u21)>T>6^JSjq5`oHu~R}P zCMI$)ZUieq5hw(+z#w=B20%wF7JEwjZwN`}fqmdM7zH-chtp+H_19Lx&VU^riB%<9-#2f4`zT>LymS$Wa2d1h%Q=Q1nOW%WX;V%?5H|$**w89f$6BqbK>g zLA0!vV)gmO1n{gD3pdZ^Ta9jJ<(wiRf`rx2zn&Yn?%#w%2D&KSTmI zG$oXMoDh8O#{EWU1HFLZe>EQK*KAKrrgZ#{QE}Bh#C-~nbF0q5F1KwEG2P}PkTnG% zO!!igEbz*sG?UxJab)~3km@&rY{zbD@s;PS6ZpwF6OZpW%=H@fa=$=gXh4)U{x z%;lYD4X6cj`gmP@m?uU4lI#E{K?N|LGJz9z2Qa}ppp$k6YTf=$AG`eJz6`7fRiG3U z0^2R?P#Ig_Q-}%W-R2-z0_20@Bj^IH?A31CNTLcv6^JSjRp9@wz%SkyDpfmfyKn#i N002ovPDHLkV1i*a{Xzf$ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png new file mode 100644 index 0000000000000000000000000000000000000000..a2efe33ae5d979ee0fc46ff80108b878fa13abec GIT binary patch literal 1159 zcmV;21bF+2P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NF@kvBMRA>e5nN4g=Q545#sPF1V zeZ{8wA>ykf1c@M_3syv|ERax%VkdSI(#EC>5et!6u@KlC`kuoX89$NwuJ~< zLC_sA)dc^hJP+EyTksR)TPhe}F=zxE)L{3~H?pPrl`W-0z6?AARzzQ!iYTnc*l}5w#Sp8KJkSM15^Vm z54|mL)LSRzX|Lbb@tsw1OO^eUvInW>aQMDFu-B+Y4{X0u+Gjx9{Pac2sC8u?QngR( zTUDTZN&A5Jt9}4mCq!qf*ih9qfzXaZ0`y^Q6Wc{*dJ3ooM}bYI8vQtMmO>>kf)Ggz zf|sBb=S~&S$SO!;PExc4G&_>GO8t?sl~FcmeFDCm$UC&^qTLBr*yv1}zL z$t8i+^qlr4a2hE*s9S|NClHA(WQgnIi}On6vI3n9cv8)lR!>k_q77N-`i%41wOuX= zeB`0K>^A_<#vwnuqpeQGy;6EcH41sp!nXs+g+LdOv(Av9uLF0%AkgxT$_>y8^jpX_we15> zqc$L80=72>(T6f?PAgqv(i%8a=rb^ZtR7;P*Z)#Uk#LDo;iFb<0(!ru{pK9?2xHTM z=A^j}|DgHII0I&^DweE#Y{nh4Ui8;pZmx%AXa!jIB$nI8I+1dZ(TiR%nerQYzao-Q zdP*hGd$l+}$4z9_sSI%AS{PvtISzfiBnU_E}XfrIN&E@WrMak@6lqeE;B3)KePx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NF%1J~)RA>e5nM-ICK@f&_O?<@| z4?a*l81oSE6$6S2B7%C*lP~b7;^Pt(Z#gSLFCJ7p33~D(f)G>;o`M7w^djO5K@k;2 zM8z0PqGtVS?MiB9Gqba^*<_S0`047d>gvB{YI=KSQ>n6)uR!?<{L@z;9mYPB$t=UZ z4K#r{U_2;B`k8ztolajaCP?175N`xGKq=%yUIGO;RQi2kyos?ZV4B}HLj8^rijxiF zDIv%=Guj2J+#cnVZRUlBMVX$HvdRpzwapf+h7 zL-|1XmPw!`)H!KJh^IlXOQ4UoI%yn3`9OH4BQMSKQ0Igh$2mSz4XGUU zV9pO&kRzqFA6q>*%U=F|I6r*mGJY7mz~_ScFfP9H8yyGdMEzN-JCi*m-VCsCCM4!BG?DA z5+{LG%)IaBk7V=K1oI@oxNOftUPRs!2PF|DTrRn)kDLLM;vQ3elLw4swSd@NPIRd?auQgl(jLAc><81 z1)obmx5r25*A2%|HBJeI28>`l2x&Q52;qfb4VVs8S}D;1?c{5tCSczYtnQC*ZC00( zSm2y@`zN{nSK1?xzZqZ;9_EVVJB?1kN4`>g16zY4VcP-ZgTP}jS^d!00y+N-04s0k zbbwR9?m{{>+hVH+D!IQwSV9xfX!zMfnGSo}C_bJE5jw;SOrW5LnAtCLb?h{FwE&eK6g`!CNnxk}_T%m|`YXL&qt|0?dF2%H zKY&V`pMiej$d2RHjM4?FoTI$n+0W}g-FPV*d0?gHrEJ!jh3=uRr`+{fH728y#76K% zQ%*>G7anqEiY7QWfNKdLFE!r=^q`lMfTx7~Rwl~FDLLlKpL}xUl^v?oBKy2-m7SoS ml94UGEafXuz5@U275D?Ku!-y^E`TQh0000)+J? literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png new file mode 100644 index 0000000000000000000000000000000000000000..b90f9f1d3870564e3aa9de0e95113b2ccf22fd65 GIT binary patch literal 1363 zcmV-Z1+4msP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGy-7qtRA>e5nO%rgRTRhP&Wt8b z3gT2s7~?cUQECQ>T4o<8m{3qX2u0wC`rthHBFwvtM35k&AifxVJoGeL7E%vQ;wNJ; zrBf+dStErCCgbS%HP_$&&fe#)d+s^jb9L_ATigY|*=w)8_TFoqv+q9poT;g)O7#j< zufTu$3Z(89eL9_`tXp7mA*cz*}K2lv}P6z$TcGI0>AW z!oN^Sa)e+Wj!GhD3E}iCP6uG3bG}8n6ZXJaxB;b>$xQGxtc91%WJl3oW=RbhTUI6b zdiVvrNPjNtF}50Wr(hju8F|?h8wDP1-ivYonqr;Duz@(*O@PmC-;v@4DDjd}2eXb(KcS2b}%~Ka?xhsRHyq6T_oM zuki^?GDbZ}Dot!mHr614N((q~JoSk^jU(&uRjO}8D`@%s1}EWTmY>Q%@YOTrHCO=l zxzkTwOXCE6{-(TlVUlL>ax88n92#JscZ?`+V%rMAg+YHm!Y^#vfgyI|pzU$fp(igs z8j~jQnHflGKYR`UsAA*;KMA%Ujr|(>70^x>mNOV0@%?Ox{r(eRkm;crSA-^6Mf)x1 zqhm)#sGl_bo|ln&EhwlBV3XNC(ku6`^QFkhz1;!2zU~H4aVmF;ks9__;1F!|?dW+4 z_%@ZazX4vf1Y2yo^NGC!!CDP>im2Z-HZ8eketi1z215NiDw(Ss7z-%$`GT=}ahnT@ zXDOV9MB<+VNt}PcY0x>=QU1ilTi`|T55XkkMEP_ZW3$lP@f;K7vc&r3K}4k|<_b+4IfsexM{}(FyoLN#ak~1#Q@7zy{w&`2@^2^+Kwi z=w5O*25*cj6DPnGoeX-pm=_+5BnDwKcKZ~6EbJFmXS`|H_2t9M&t6GVCQg9C+F=_U zR3hQQvFVgJ)7blr9;wntFY2FyUv9_I_eMI$80%x~QRef`IF51~lP{y}0v+D;G2ktj z3X*Rd~1_q?o002ovPDHLkV1mZfWvKuF literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..75f81bc71afff7bab62278aa6c4cd9bc26c4f603 GIT binary patch literal 1373 zcmV-j1)}Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NG$4Nv%RA>e5nOmq;RTPHZnyHzV zT9#!|5sH#f5S}2xBqAt6x|l%;(St=2y$FRb)k7~)`A`@k2$4N>iiqeURM?G(veG({ zNd?N$?)U6&yYD}(vH8#1XRo!_Wp8{q1AgY1YyRUOW3Ii{nsco^VZykLpMm<%K(pCg z0H)Wk+y_Mp-vng)!C8GsS#Ju8{zla&_9gA2dNcG`je_ru>XY^W?SdYstxuj}CxSz=tVL)$R}i$3%|2wvk0ZNI&TyxZHT3;xBJB8V7U?&J>ypz)Voa zbbnn7{9&;b{WWF8Mq(&xS_I=y2G0Pu-E>Y2PSqBz89?`e+p1E!C`<(}gBc-!KLxx1 z+&-c+H#k*Wv`zxLp~K|QE38YZPB_qgp+n#VNC*8 zn#ijz!0~BdyN%0zAIx%I6(6mw5;a>_NRPl(7Tin+Gd3N(?i~DgK-W)>w5Io^1NMQi zgE$MFlj%dwoPdJi=%#xUxV=TEb>Czr$r(gv1^Cy*-^TB5k%O2!fn*Xh;Y!$T)P0jv zXXY@X_qj0sU6}zf2(haPh!6Kz@GfwBh0al-SGGk%Pd;BH|DivSs|Ts;2}lgSwiLU7 z+e>s>Ye{a>4g@sL27j9H9{lY06bOYTkWAuu;D+eSyLbVpFbhvWfyAkpk3AFqv*5_F5^{V!_zQ$Rhtu{D;Fva+=~a5^SehfpAeWkef{C36 z^fS9XO=q$vq`%Aw=0E7X@EJcH{A|3(W2~)(RC)puBYr;k%#z7{60{zJ_$LEx71Fl9 zt)S!p#QTk`4dsYU45zM^UF0xYE5KgUyb}LW3Yes0a8&3;;0N_fSla^I(jZBtUm%3g z(a-KHD&3|g(K>1P=Yk(W*aH#oErb2Lgi?vmB)PtBxNV`+2p;|b_zCESZ*3lJTsLug z>(ZN>IFfox@`d0F;Px;bpG3zs1K#Z(h`-78+k6PMTtY64=3?+Qa2xZ9lZs0(WS=0A zy~;zVeF7>9-6h~#;I`2Vb{~@7KZcC_H-6_!CxRjMWCGGh`yB8+aJwgRdkbNslko5K z@s2*ko=reW(N8~lROj7Z5Pj{he$zl=^>3#=VNsu=&I7)(s?IxHhraeme}IFa`!9o# z{gsk#&hF2%7VyzMAN;BWW*c0BTA6G6gxQx9K*2Wv{n9dBR&)E3xXvULeFb;|l>5J+&SJ*3 f#?QcEcn1ChXi{ddi2yAg00000NkvXXu0mjf1TXuEP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGI!Q!9RA>e5nOlfWQ5eT(T*qZ* zC~{X5xxRQBX?UQdrlc@DNRyJ1a>+HGh9-HSgz=yx=7q$I+lvQA(u_pLZNy}f2Qd#c zm@yo`@3hzHJL{~y&zW=f>@(_o^|!wDUH@y(TKjSo73C?CiNRh4KE|_B|M`mPKG*_=*fn#SQ&0$X10!ty#L6Ptfh~O^uj);vkQ`_uqE9mZv?IY8lb2$|PXP9x zJ}dHu9QD=#Eq9DBa3o_cko&fgz^5rep_4ZRsoiKuc;hzX^BoC1rIPYSUI@aY9CRo? zUFfrY$$Lq+R6@O9FfnrFU#VD8bJ{kpUesI){z`FAni>5cayajrNXC6WMf+{r`1Cuj zIEh;4ii_KDHmTqpb|Ah;$xDBF4hPQ_FS%7Ow7JFSIOI=cWUCIs7&&>f^R?2a@Goo|G6IOhyXoI@_Xnb zujNK=qLkX?unhwCQ@S!Kj(|-dNaT)i3}pOzkkr7MP)F`EE{VT>Tj6pZD!@0DaM{Ep z2;p3UvC4CFGxh)(e}IxDSG1GilK?Q z;D3;qAvwq>5s%k>`dxF`x%w5@H!I&0rKhSSlz3egf8HUh(^7kwi)8@Vec#I=BgGtbIV`p;J!>LK5(=5Cdh%ZGPD+)@2&rTH?D z`RlZ%LtsnI0~qN-nWZ^u-L-|14lc>5Z-2T%_`3WYGfkD<%hqXA^I#Rim1gPQ z7}9nkM zYL@~1Rme29Hj{#hw^1ET@^t2{K);_qW_}C227f?UA_sH>&`;xw?EBiB8nB3!;5Ud` zPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGPDw;TRA>e5nMr6AK@^5Fu5pQa zP>d^hh(-y8#4WBd@q2C6@TSu}(>*iJ-ROlp z&IVKNrHJWI04pys zM)(EOw$nNqeZwA0d%r$l=HoOgVqs09&`XJVmrU5 zpd9kZBjAo@FnWb1Fg}gSrwejvk*Oq|O=E%;~x-=VjHYE#a%vS&p2ewl?{>ohD29I`QZ$w@CR9D^?*oMru=0L>ug zMb3*n**dtlgP*`kJ%)US#t3z?l;ze#i~o-puO-T}BZe)_1^O8SmV#nGYT9-IEoc0E zoq9Z1Y45ns|GANI%m(@?J*6z~Mp5zo5l20;WH3@R7McVhsWy-4P3f;3_@M6doCfJ zC4@sLZvquSzFkLygmL%;75fhk`QA9s(veq&oaAO8Hv_pD$jv}zX5cTo;-}rI0gAT( O0000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NF!AV3xRA>e5nLTI}K@`VxiAIeP z{E8q1K~S(zi5d&hC{}_fh$1LT3`DUp0aJ+~r3hO1Q7J~n!ooBP+KC7@7JgM?6AUI1 z{Hlz>m>AFBJ9fNxcQbptxt&~ud+=x8ym|9~@6GPc&fZm3Riv^4epVozPB($~0h;_o z@yJTzw}Fvc9z&HxT^%xez8b4n`ixS;3Ybxex{^t(0PeMFa1TtF`z~TTj$c2x4%WI7 zjctdl4;bkyMu20paW0{iV!DdO${A;Z*=^#+l^yEe?u5P&e2Por@IRiDWJo6kK`-O& zAwFS4y{S~{gmHkY0evf&ZEO)**(|n$R!|f8kI}A!yFci=8-lhuRw0VH&CMKdgkT52 zqzd{t3PVbqnAA+OGH=3Z`db3qbJ|O4JdHlU3cXUcl2!7!0!gPLI!cVYsvlj2EY?FD zo!RY4%mrW=82OB{$UUQ~DzR-eEJ)NbR(k~B4&}cL{etQjs57bn$&MoK(>zp}wsRG> zseX8nDZADlfS>J6q<#*1J<%KsId+33mZ4-LZo+dy^pc!~`Y~ zw+6fhMt-8KN`QL$C`foSi2ZJuz6>KoqJXPF%aNkf@b-TGCq@I<1=fTm#CW`S0~5{z zkvG6gA@Cjsqrk`=l+3BXRt#hNjbqTBv-xFgILO0dWRKHviUSbK%IoA!EIG_M1*b>G zk#@*9+TH_m%^>YOr6;9sgs9F!)?%?~lRgtQQp6k?v=yKy`OpU)q#qo1W0t~=jPS<( zWjZ;nx=f-T%o$9m1FzikS_bJXcF{Ao8jPt4?k_~;B&x3hF@aV-WlysD z(LZUa_9-y(0>xIOmkNj#Z_l@70ZFIHK4{O{{F1g2OAcsXRP2I1KT=Ex>cB@uB&z(# z)dK2)90QVsaP9^JK+C>J3EP}t*$LwQ&aZ=)s_Ub(EydzCGS~~gmzv2G=09UjGT$K( ztpGQHyhwbD{I}2zW))xFtcUYEH0zQ%&dRp79xMm7dMp8b91i)&dCPV=kpN$XqOt;& d75JZ4;4k8eMR$H}Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGmPtfGRA>e5nMsIMM-+zpIk&SU zir_#CqA2LXDT<;9Vni2;x^mS{C{Yj$qCpT>5<(ECg@Q;cCQFStELvOr>-;sIgbS7O5)`9EbQ`j|%tN=k5HFfrg3<8$N1s%f_;#lam1>b-R zKy6-}5^S<(sRI6nXps+0pjJ0=bz(URWx$UOeV@0C=djTdMq{g>jWx)iV*aS8Yl zOh_eX1bO;c-9_MSp4yjoYu-<9DE<&Qo0iTlL`kS~Nwn`kaBe}RxrfG2qG@jSj(`-s z0CENao3z^5=F^GqA=U|85z*WDJ$xm93;FSoek~;bg=p`MaUsb`9JbO6Vz!mu_;+MR>C({%xWH#MlK)^~85b{{?=Z#A1N~G&%!4m(|nn zUNW6P>;m+~cZU3~;4yHvzGR`uLBu8lz0Y=)lzQDuW#aa!#kP){;~o6(vy!rY1AP%b3GCBL?^LmT5T2b_?L>JK%m~Rb4&0xC+RV&c z*r^N16etscd5j0Tb?SnoN%~y=sJAnbv%5IKf7IWXm5vnuQ@R@|W@jR2%emJcx=w1# zO82^D)3(NktufTqmtW(FGj-A$BzdMRz}$@*Z%Ln8_KvZ?4V>M>iTku@6C~-BQ^>am zX~%(<`ncN;ZM$hN0=2mz7tFn$-*Zu@p<|y#{Kw=Q#_WVyZnNjTL9LE`uSXV*W&13m zHUGhJl={K{;7D8zBGq6m&@TdXTg||JObN}S~r`*C7 iy~-7+T!Am(3j7bhQ*3o~CF0Zo0000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGK1oDDRA>e5nMY_=K@i9N)YuEL z7ovz2Q4b;*L9w7G4^|Y#n;~ZF`_3?!4k291rj_c2qN|p8@5Da z{7rZZv>TQMf5_4l?T@pUWtTGycXud`xYb&Zk9o}|OA z#8t?xU4w}asJ3DaO&iBKp$a@l@xqqz0{*geiDKYWW*N@4VMFB6ndI8Kq<=7T?i0bXHC}wo?Di`ZQ2!g-iVbv;0I{Wa%zia{fhD zO^yR~z|eb`p01h12YfI=7;Axkzg$D6w6(wN93o&YLATB^iw zF_5A){ktZlKPs69c7sPiZfJ&te*|`csb($U$Aae7getCx;z|M(8NEF=>n7}CqvR}2 z#O^`_lrN&3&HF?pReHJ1$S!h=UF56MJF(IP4i`Xg<>qyj05_B_X&BVW#%N} z-wuSXeAsVP?@aYhnJ{Jts%BWB{JO%Qq=5L}u5z$hV%C9YwqE402EyzjbriM($SPj} zjYnaU9mZj&a*`{fZc0t%nWcydV5lN4JVx@H*HmWgQOf@d?yAW%W-gzj?-S5}jQXQ4 zp2ANQ*Oam#7ZtAtDDox+%Bp_^m%&!hNUZ!|n5BUz!+pgUjwNyGpHNg4#E>uf9iVAS zl)aDM>j}gp-p8Drp$wJtw5}MTpd(9mNG+Qjs+Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFlSxEDRA>e5m`i9BK@f&_#rQ}> z@riix0p_wQil8XIa`17AU_=iR1W$U9L@$B{L=l8s1W&$>(G@hF)F1>5C_XP5adU_X zLKF@72m}%}#PzFXdeb}Gy*rcbT`yDcZ&z1${Z(B((=)TNSR_#eq6$P6h$;|Oz+nZ_ z>GTee1OuQG90OGjLzIV#B$t6Zz$CpG_m?MfiL4}611^A3P)wdPVM~c2-MEuT95jN@ zAgr|EFxy2Y@yU=7d;@-$!Nwx~iZZvFV9+ z(@&A;FWUbrBt9LS2E#zfAj&1M2P_DiAwI&n790fiU};#6K=UEq2l|1Mag=kQCI|uZ z%fp!%P{%=DT2}Q!#HZWqCy%2PkdBK!}|OzgY`@Z|i+$g9lg z#LtWgHTFl-U8yOEx`2(lp0T|kPx2Pv&1m(_T%`5o-NvPyqG$Xdypjv760o z*<+w2yCWE?ft=MYL_T_QE)DuE7UJusOl>I?R@x{5H|ynv&tL2A!DiB&w3R*bW4s^pax^OBO!^!jo-y%)XABA=r-3&jYu0FU4( zZDs*p-{p;L%kdt?`)L~#`_w{%`j~eL$TL7mB^F?Oc&P-W4YLEfpXi-_gX4Z1MeB0R znM=n#A@_xAkq?>kU{-E4b1&yT#5~1rCCFAr9|8T|ush_A$e&)lKrTfc@~4;o^&;0( z>y@+s;b9TGXl{Y|(znPL?0S;&h1Wx(CI9JF@&Y7b79l%u80-Y1e*)QrN%TAYNTLcv j6^JSjRUoQ>^9uX}Y|Szsn3K6a00000NkvXXu0mjfynx6z literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png new file mode 100644 index 0000000000000000000000000000000000000000..fb00b5482c7c3510a14c862e9142ec5b021b18f5 GIT binary patch literal 935 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(<^v49!D1}U6i==L6{T+q|SF{Fa= z?W~P{GKK{3CCSpnhSQZFLNI%_qJY7e)QzuM7K9p$Bp;fzxlf9&9OEg78eJcD2dZ2iMjYu*y^id zzwBS0_*iT-^G@lO`{oPpi?Dx@h*r98q_&|;f+vsvpWHvzf716-?Jrck;dZ+%R>Qcz z^|(}a%%S)nKUZ0|pOE}xZF6iIN7XAnrswX4vdo6l^VZ!-_NxtUejzDTXW%<)+8a?5 zpVcvW0>@HCt&0VAap`W%jq#36I&=M2p44Uct~RTC#W9aRS+>d_D7UWJ>@W3bxoqu> zbiVz~?Q5bO_9*TyyTzVx##F_=?fb#RzrPq9Mat#sw_8atD_&v$x%)xM!Bs*6%lGA{ zIZd=+X+M3|eDkh_@nJ>QB4W%fcN8sh^ux?0o#NYroPIwD@L##BHd(fGZOa8ki)>yE zwsW_bx>`3+YY2K^((uFJ<-fqwk8hYW_j$=!A&Vv(R3|8(uT)I84RGosEck+gZL%+``Fnf-C~r269uGvcdwY8|FJx4!TB zq05k6kST6>xjMi@k?p|Q1+Rto1WcdtP5Sg*tz`?6@FYu@1@jNc>!oz&`p;c+7nDgn MUHx3vIVCg!0Fi5f00000 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png new file mode 100644 index 0000000000000000000000000000000000000000..285adf589553902122a56f83a121f6b0c291597b GIT binary patch literal 1632 zcmV-m2A}zfP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=%1J~)RCodHn_H+ART#(jK3bY& z=?Uy&L_wYiqKick)_F1rf+Xky5pmv}-28+OYuor}i ze8`u44&)+7xjH0213U$O0%eJOE5?i{Nmt>7WM_hv-~gyf6iYE@R#Br@43ZlGx|&rI zL%1GMY~?WGRYX}vBs33v3Wi0Li*Edb7ZMo<2Zx23t~`{}_`nzLvHtlBUgU5UaN?x5W!OPohgejC+o5pkpq{(EfQ4D$0F{OWeY3aXbc2hGvMp?lp@F z2kvT!-8&KDtA+(#Zo_wRs7c_~2+7IC22)1p7lYTq2jE%IH;+L#3XX$N*@A<3lS!Pd z2+b(5pJY2fO%S>b2LHdHyT{OWt)Z=tYDL<&*D;Z20VNwlzDOs5)1^6%_jB%&ZX1pl z=CpS?rO|O#x9{|R(JuBhhL@*}J&(5->|QYFrc~-}Pfi^q+nsE+UKA=<;6Sxyij^Q3 zo{sg(Ob_lS4tAU1e=f(@b?XfKw|DDUFzayK1YvbQxXNhlr#zlA zyE=7jI=sf9O#3l3DWp7UMPE4$d1IYqb&7GsQpe%V}@BQ)|D*+x*OWtc zoFeu8--ZPAG3GwtBV&aFc{U^|y%P74qZrM}3v2B`GKS$(Y*ytt$~kvu&be5pd}F*q zZO39I(Sq%59+znkHkvM!BJvFs!&P=-5O*ODhqr+fu9?t&6NpZdd;%@!x{AIoxwWh- z_7Kj`x@JUsUFFAt?ib!SZrLV2n=lM)?-JU3NGsaq;3 zsHXY?WEsSK?3+LcLHGIwt;p^h;yesF`$FP*-GjKR&LybUt3zK2h2)-P`zI&XgEf$& zCx9UF?Lm(ab=b(!TZuQoYY=lZh?NjydXL_P|4?vjK1I9tfWD|NOOE0AC7@nCcp;G| zKoQYL3k#Jo+Y7;i;C*lygo;Rc7szMN|2twcw{CZU9;mxeTPA*K`l*``0r%eN*H#pTVYlp|~$WmTc#Q{tB7<-Em%)*iHkN zf;qtV{+JiS`J8JK8o5pYEy4Z>^xo`ip#QS}%r;2yF^L1sT^eZ^Xc%Z1Xc%Z1Xc%Z1 eXc!nU1OEZO9f1_FuE4th0000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=hDk(0RCodHnro;PRTRfPT3zj> zp(&-ILgIr+%eqBHB^DG(e$l9~4@QudAA(ZKi133Xbdew=BI-j>kyMl#V$kE}E0PO^ zHx0F-BE<4RnTd}&{T7@9%iOK1SpC% zG^}oS7F7Kb%Mh|k$K=e&8#vpzd^=vTk zt5Yeo24;gzpeR14QH+Zg=q&*M0&8rGR)j`~>L!40MU@BPbZRtx9CYS`{}ef0lxuxC zqVzWkJ?g5WpnVr@L#iZa{DUCm%E^|qqDl?kv1F2;)QW6I!~Wym1P%f@I)UpcWhkNE z?MM-)nMz)=RFmU=5mE&jgTaoRR_NiOkQ!8DsOXu{sv6^tu^p&NmLW0b#fo{e!{z=} z%gD#sMRW$Ja&v4JdAX$`2Hgaz-glb0Wh-+y$5n&*?1>P97qO8Str*S^7fnOF3^%B5 zM~>fl7dq+a3r@5Y!Er88WBYL}pA&O0+}Mxh9cB5=XQFZSEG!c>_WfhvKWpG>sq4y! zW`huW7z`~FHT21)y;sBM#9RX}%FAUg-`d>qDTg5j%{@h-+QH9dzyF-{qq*Z4hrQ(A zT_$8Qh_fg+)EmnLjeWfuK6wYho1@_xIV*j9lR=2dm$?)hE51?+-2%`0wDU>-2H`Cq z$!gH`K0#yuW+i{Nl4qfH@$>RNL9GT&w^ZQa9-x1#htur7wYd{%E06Y78ZE0qS87C+ zoVA)8H20qi(3`5%)X?gX7LxmfhO9QIaihFKBdX+lpyW-4=lm2u&Ucsn}hYx0^o2+L|=ta!&-0Er(1^7S7Ye=%^PHLseF_>|Df z3dYS;C(aPjnFe|b^n6XnA>5OZioZ*ONxmwS{k!1>uL3akJg^iT0h*Adk^AF2l2atf zC`~mA&Z3-jpF=df_X#*-!H1wM|=Pl8r7kZ2&#o;6p|`{{5_Ui!fMjlo~DoeN5@ zHu~=XTR=Yc(I9W&{TC#BEnkK4Sk{pW106X5>kIV6DDN9QoZG=_@Ga;9!wM6%x{<_p z0-1<)xmC{Sg|7POdjhyZ?jtKfr9Tt7a<`;+LC!CS%ez&u&TYy_e4BLii<==22z z%rsWN3;xq!gr;hE8;tr*x;)KV{-&(C2aVTEG{c#|{tMs-Cg6PohWCADtaevc1LyG5 z-lQE6%F`HRef&0SxtJY|L2H@=l-on_W?|09N`57p#vt#?e@O*}?><>R6aAFqZ?bJA z`|@DuWXvZeoTyzIgXD~bMvrpfeelZi9Hw8MqSG;Fk5aRLXxvBS|A0c`7fXdCxC(TG z>_>19$4`RLpSh)kFfPRn0kULijb$MjNiqUV0mDPapO!HcD<7Md5JTmk$J-;A?A;c3 z;4W_uXEL*7(wmhg$(oIP(YIGH>5)JtUlx1l9M@jXWM<3cM}zmkNsy2AG@Nz!ouCCX zjF7A30U!%v`@w47PrhTDA~}#8NDd?ik^{+sPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=DM>^@RCodHn_q|(bri?m-PBMbT16!@6Mbv^P77|_#OCi@BPjBea|`H`OVC4elxeNEm%+> zC=e6~3Iqj$0zrYGKu{nk5ESsPK*c+wg0NbxK7iXcunDXItHDE{8!Q9!;9u}3_!Z28 zDKK8CRQ}5T%!@wu64K5i9{#yG@7hz?a|)#QMQXP&$8v*$%!1MVRo4==YzI z_#pVc2vr=M5@+zfP>DoWfv+7!G^0u4t}3liB-anFHA9Jn7!qI3bLBA->Hr799Z&|7 zJS3lvma9Y(?cftoMw7hSTPhL>9516Xk(`dVOdyhYH}tg0y`6-5z~9Qmvbw#eO`HIG6hS249xZ1s zKLVXnB$UVHtTjP`jVc13vhte!Nn*1ikvuMPiI)2|lhJ3bGU#R#vBjALD&Ueb5plZ$ zwt=OVI4)l}hQS{-3^(wZW_y}l#G#m*bcm%`i^-BkZX=*;)ZQ}^@H?qYPMw!^67`C) zT3MR#VH+GIt~Oae(wMpqwLt8dE+P+TqDOpW-N%QWcaXT+WYJAy1GRcIzB(TW`;@~s z>Q=^cP(8msUFAwISV!v21%DQO6|1K|qA6W{h(Y#@hR}nLTwxAn;Ia03S`)(}(32WM zPd;+BG|i-myTcfJt&gy;wZ$x#Wuf->RN4!M;G3+!H=cQZXMX zPGp(aVpc|0Mb1SP|p~EpCk7|AcUEnDo6TR2L!=M$m zfIyOqA7cc~#>c4Qw=6|8+)Hd*4&*RugR)>h=tAH9+@rq?USwNps? zrY=`l5{7Rnkol6_&SbF{Eb&r($v__OXy!sE<7D(xEmy?*X@0|PU4o%Y^#)K)S=5IZ z=ZQNcESKsub1gZzmL^uuDg1dU$kwEdKRM%jlQb|su3J*L=UYxI-&iFxfl;uBK#Fwwd&G@_jH`N1@*d_F{@aviUG5!@Zasx-S(f zh>M({7eJcH3kLF{fxK`aFCNGX2=XF=ypSL-CN#rj)gY6pmpfeSR5nAq-<3I6pnPqI zne)hPOeV9=gW^F}#v4lZ`=dPKNG+KKV)XRTzpMiNM{fJUZjj45a`fJsqi>O2e}{Z0 zBS+rM&uy7U5Rqj~xNPml|AoDJtU3GsYy z`U=7WjF@x2i8J%Dr=9}~#-Z~${u{w-;0(A4vY7Nc4PFInG8bX!XqpF+lsv?n22Uts z$RnS(*ux)3{o#?(Cy#vuQfTz=Q1U2d9^3@7wiNw4)FfQ;e6E~EVM9P;=W%)&l;JSU zC8qTpBrA%i!Q(*YK`X#tK=$-cU=mEQm*sn~pg>R{C=e6~3Iqj$0zrYGKu{nk5EO7L Za2IM`$>Twi#ajRX002ovPDHLkV1g*&ik$!e literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png new file mode 100644 index 0000000000000000000000000000000000000000..4fc64ed179136e94ab9fe2ba86c0531578cc0059 GIT binary patch literal 1601 zcmV-H2EO@;P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=t4TybRCodHoX=}rMHI*LtPy|2 z8qs1gx-j4`RIJok#HyRFL}_s$CYC$PT z7A|6~M$tx7@i+1FeYx*3Id|sGz3<*Mxz{=H&6_!M&di+eo0&WF?!6fqNs<^y3?v2; z1BrpeKua0u3>(+d($W~dSA$E3tz(t_7ODSqr_(uGrJceAWrXaav7KNC7_ZXsIrLqi ztr>6_9I8rKuHO(d3ig5@K+{DrD3;M&paI3e5ky7T;wR?s2>3TueS(hfWHfyf3m`}k zRC2H`uFrr39#@!piPwBzPP&UShU! zYfdas#RTk3IT-WP`f~=javQI;08+ij4zb)dP)p52kr4em-4oXjcq*RU`4!r zg3#*VX+`^-wu&#d90x8zzEk;n-2~S0rTJpZao`eEN29H)BM}t&O3#m!4=m0WwTCg9 z(p{!Q1%$W{SI6Y_!F=5BN55IuoA6_ouG$YX6}#TY;6Wp>{Fc2!3%K zUJThiZtU))M#`SZ;l}6{wZbo^zDY(VtHEoBH z>v8&!;HQUi_W4v=gM1a%q_YI7+Wp|yto{r6yb0V2ZU+~Do@f+53rX*>K7HI%4*R)Y z3G&7B8UfGS0*JT`-J8IU=oir4YwgSCt4y)7ZLNwuq_!h0j*+s)R!NYBur ze|!x&x=|-xchYx4zm7&u4%<-O1nIK7mU7C|_$0ca32Mz0%ZSl^cq>;}MVWlvBk13P zjYp3p1?#b9+NE2Wvx+kLx(S-_ZRXq#u}0~Bf2B^l^_lcFCa>(*9$jHo+oqVvcja#~ z(FYV<2b*pUL5$3e1owamaE=jOblMx&KCqYb*O^|kr5P~}bzj9y^|fZ-g^a(l8ufe74d9YM3p%_` z2g*vRs}STnQuuVXLp~c_ZCtU3PL&0JA9o!|Yt%d*+in=2V7AH>J8EkEf=)&6Fktf? zewKhErY=3f_J`5MvO2831h&vdsXHvOio4|u-$FlP_bS7F19(fr9?XG9dS$UsY##%s zz@Oj^ko%(0Jp@$$BJhcB5*!6DgFRqNtX;Pp`%>|izN^t|jD~d6KNn!HJoJf=2(}MP zgv@K#({>?(s;oiXPBWZ+2gGPV_-O+-ly9{18VyQ+^EI~Jh^kzI7Ck-A-SPC;G*#t` zEysaN&}mPk6CPb#RKD199P|ldP0(90c1_Sj*liUX+d{@cI9^uv^bn_^r$2%+y>6Yj zvWd)7uA(Jr#iZC=v9Y^l%V|bXdXPL%%SsI-rB@MFQnE4!LFr`{hmwwy?k6EhzwI6a z|NGaWyab6UNJ=l%!GpbuiJPvlCpb=G3Y=KhwCb;7(u;J8ai9bVk{1=|mdQ5oB+yf( zO&7(WShi)cMdJxhG3&{c8$-7X=%J(?U>r0-7U<**&_1X1YvF|nvP@)z>D>n3q0gGH zMP3Kb%KunkEjpgsObjFj5(9~W#6V);oG|boTw{sLTC#~k00000NkvXXu0mjfk+$jg literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png new file mode 100644 index 0000000000000000000000000000000000000000..f223482090ef6c124adbb07a0dc60a47e3bab91a GIT binary patch literal 1576 zcmYLJdpr{g7#*8k#xC+^yPnbQLD;+>jcttVmM~3}$4KdNy~dS`jo6Y`k(fvGE^$XT zmPC2gyoXRjDvPMNOINMB{B!%A-}%n@zH|QmXvgp_P>3c3002O7u4vC4b={>jcxQUA zx4P_zM2x446QF4Xwz9LJNxryH4-dfp9WM=#$P5R7b}Kv7+#vt}tdsx%cT{5cRw?;^ z>RJi>;dhI9rr7rYfK&kvjq*y6STE(>hGCTZ!!{LygF2Z#d2b%3ns{X|XQ)qNRQ22_ zvM9ygnms*NoK(}qvJk!FpXd@D5`sPhV~{CRM_O~N4~g|S7THPbN5fMVo^zdtSNME^ zxjp%vNR$@IU7fV{j_Yb@YFc%vI_^GvCjfdxyltsYbIY6)yH6%&pvlt{~QT4f4-SeNAhlZYVx;gjovKrfT=V)Y;h)1$YqH zx+JCx;PcIiCEw^~Nl%Z{->^=uCs<7>BgY;R)u z^yNJv1Od^@cyv|4VovTmIB12di0!FuAHywFOyN(yrVgRV#rQ`3l>6g}vmf_0Bc;eC zo%m+~(d6cbW;}2S^~qXR18-0L($~e@Gvxf^ZP|%$9^`4y1vcz?B_&o(7cZ&Eov_4% zYBsyi5^*nLy5E84(TP=4SWBBA5F2^RUOki`#Js9`ugB<%5>E|dW)mJzb!4mz2N0yIh#42peab6 ziT4nblw#Ad-(;Y*aKvdj_s)Crmi(Egcq*sTPsgRtZ2`i?2F`*6HAUEcbqsb}*@iT6 zea0}>yM(IT%yGOoqN~TbwWcVF94RvA7+Ak$g%WH0Zm{Tj+buG4g9cAyOb1{!b!=c9 z*Co}`hO}VIeSYg!S&*J%5ijJgEENpDP&X^Tqi9hZ2^u=g{HJ`YKhD8VgCZ?VjJiVG zG{0)XxC26EmzSZxwa^0IvVd5El`R{Dq8E*DS?r4XTws!QN-6(sNFX-bd6r;$BDrB! zUiYPE{f1i(@uQ(?{7tds08rO{EKq^cc_^c<6)uX1ZKKtk@6d*9&Sy^7Ct95EP_&#r zU_bb4Ee9XGO~-%LJkW`-aJ&SXGn z4^27@EFYRuz|Nc#UWACD^HMZNh~VXskE0U5iSicJ6X2Zy3*m*+@iS_4PP_9PD0HRV zO|QFgWJ#YQNIHD7i*$`2Z%hH-pw4{_u}aeF9a8_mmuxaw7<%H4*e4#nKC|WPrJ{ro zimWzz`78}Wp_(6sT3pG;S8Kujy}be=WPY{*nHn*SqHT@ryi_b0RuK`cX}|$QeetZ( z(q8=1DXF_hvtH*791R0yIN96KNbnoigD{v0I*!#B6r9Uj=8v7+R(nkQ!*-0f!8(hW zCFd1@aMVDOBSyy}|7CK|-KSxX#ywH59YS>thpj&=4CKJP*5%2b6;nuf4uT#V`3dB^ zzrs0DFf{O4;&OLFy^uLxI|>DkPxxKbqW2lN9M YQzA%0Xq-%u_wJX*VesfCr!$oQ0H-|1;Q#;t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png new file mode 100644 index 0000000000000000000000000000000000000000..f2d15bb135ab75a9277049a647ee06d14bb622c2 GIT binary patch literal 1963 zcmV;c2UPfpP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?6-h)vRCodHoNI_xRTRf(Dtp*i zBW0P|%d!_e6g7KTLJ2`=BT*j;1N&HLSkVV7NwU5LVP%m;_9cY08a0DZvXV5)vM3`> zOPsRI!tt4wIsN|AxtHy_`@F9@=W-VOxqGd>*V=pi@80|Dv#(=QQz<0_B?Bb`B?Bb` zB?Ar0Ky%i-y1Ker@Erj9WQ}o{{dN(5OLKGc?mYb@CMY0e0-d#iv7j|i$4Ah&lfIUL zg`hnzVKw81m|kEq_#G5ol!J2VRg-9lA#w&0=xqGN{IC%JqMFw*@HS>sM_dA-1VPRS zoZkg!#sw*8{Z__34w6f~17)dK9(N~{;2oJyX`1=yLSoOP~?78*?iR;ERJ6|a^AwN+S|7@G+m^Np97E!>_H zm#A_AcBRaZ^V9yb9k?%e-jl6RjSd`1d!biB9`_zrM-A6!eEKO=+GvyuS~2UdnB?E}Yi!Rz1v zh>}03oB~4Mf2eyI>;`eNl?ESxnV@&lv8o;I)8(7m!5Iy{H-r5kjjW^brB0acBDTS4 zf;es0Q@+;53)5+vh@jki5FHI-5c9zCA%p1(v1=)|-mf6eaPl9!-OjKCh&&cpUCBuxeS+32tfMC(cUiRq|6{iiw` z8UJoI7eT?m9`gk5kL_8onL%yuUOj^2D&bNlNdM<*3&R*ejK}5$FP&Wza zY1IKqI;&_Io`7CY`Pma}u*a6ll$#)C(Lr!0y-o(cD+G5y%_w?`Jr8soxYDi6S=Mjx zRwDO8+t{b)Ca4k=l62V9Ay8z!1$+a>TooPkRzXtkWe`NvvbM6>8q(@@BS;-X(mt>N z+<~fZZy1;gmVo`hiZ;=gtTCfL$m92;$Ck=eSAyK0AxTT`D=-U;qfWEy8DQVdZebRk z?)qjd+b8Bf#OcTwtLk>x2&(oF6d-9Qcm(wYTZev`$ClUx!8*;~Y8*Dx-@nF|TFpfe z1M3Z@gGFFM!rpbLv(m>JQtJ27-rfp)mNJI7c`ky8co%pQj0f*P(o7H+({~nHjejPg zKRp#SGhI1=GQ%}wEypDj7uPP0$8lK7pu^t2wQ)acf@&#jHMU5V__{^V#hR``J_Po0 z{wgtby_;L|-UsPT{2?=no6vOyp&#aSAG8+q1-iSL6qNa>%G_!xys(6Le+SjNO3^*i z$sx`6V4o3Em)*<&65Ws39`Kt5vdVin9x{v3@5verKV9QqW5?*zX_qM9Lk8yyl)&~d zZS>w{AK!7VOKEU7OW~kt*p9x>*y2?6{TvudyiemAXR1%iXjpK4b6_5b`!!-YZEgsQ zBRlou!JA+g@QMCq#&R$l+z*CE#q-tSlV}Fz-Gi!q2j5)xw@2q^QK3t8p%rWbI@NBZ zUFB{W)i1PJOpS2VrEUbdnULVG=)%XYy@=&{>_J7$JMoxZf_8bl@}6)#A$yF;ms<@7 zEH||7B)S3(z6VmGU2wyHvr9esQo;{wYF*B$z4xn59AnpZXc5 zMj%P|ySl3I-Ro?_-VSt~p&#pN&JNgmg6N#1N4cI>6M)@wFg58OD)P^vyadS;l1A{M z`yL-jYEpC&IkA6GXP;u#q&XAl8gwLBQ#CeDK{;vW#9sA=5+p7Npr1`ffhj;stLUN} zl*_0fx7d6_mzecr$+ck9T5bblK`SVNbTY_gKf>tK1&8l21*7>21*7>295{={{a@ID#l9@w!HuV002ovPDHLkV1m++kNyAv literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..50fdf3f70c45ea4612833ce2a646528e4301b3a6 GIT binary patch literal 2070 zcmV+x2Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?fJsC_RCodHn|+8CRT#!yze+L9 zG*ir0kODz8lLP}>>|6T~GLk5fBCLocFe{9p=mSy^L86etr2a5cOGTtVOcIO4KGY~M zqB6oTt%!0{)3)DJckZ5h<~?`r+?lz%+uj$R?m5qSzs}q2%$#$^K7E?ftU$8@%?dOt z&@(I0(a|vyTn)zb%o!AzHAR^Pegl#}!QBOh>v^sz$fv4|BY)Fw7Ag8)Nin{6iW4=@ z&{z=Z^y*&<@my3D@AowQ`Msq$Euo20g#L`J2lEV_({S@!T3R;wW7u5>cZJUv)bGIW zF>na%C7&Y&#j)Ko*#Y1kV96=STP#cXRhB`)++XhISDz(3J$;8 zGH3v&hsjECmX%i_oPvROfh8v(^=B0m_?Ik$25}pR(>In>Q3SyTfgOR#wZmWK$A)VG zYXUZnpjY}irR@iA(v~A;G#Gw6xY8JJhnvlfa+f=Xjbi9tHPz*FY>&j(wcwI~&pG6z zoEsxdcnH`HEcqR>QBSan2^05ODtakpCu!7a=^Hcs_kA$h`b4nG`xCIv%&hMQv9 z70D5E3^-=wqbs{L*Vs5b=mdJqa?ZH6L=HH5Zu2OeNtRua95Ls)NjUBIY3KLo$C+-r zt}L-8hQcWDrK{+)kIts||6h_0-* zOfhf}lUf~OI05L-$`bt*~ju!k0bm{0(xn* zYW8HrT{HJEZGNnUcJ84*b!%;l>l7&EfLF6 znq+)k{9OjLkhMe$-*bJNP#@iyU<=SaPEfn1{b=+y088!<#WQ)!gQ=K;#OHKiUFHh6 z2P8gK&{+nw_w0)v-OG~FL1zTe+r2NkR}MX!#IG;lKm`0G5mmwW)seJF)w zOjnKy5fY6hUPos#I#vSLw*jZRWEcF?eCELBn0Qm2RvaIO1+wG>cP9a;|b(lInfsR z5$S77qTyeTg)$|V7Vt8#L~r4XLbjQCoL>O+Z^eAs4{?6x0694z7ZvGMKgm*GMY<=a zP;oanUmghj6MTJZn0T1X47q5nwJwmWUJ4h~6C`o5hvVTm-VeqF0%&h|7tp`7ITO&y zn?8!e*Vvyv?m8w{?G?Qa?r`~1Te;nZjs68wzCz%s;5g_`qL;ncnLb=U@KzvE?N-+J zp+ZtgajYX6_iZ$gLqlovOrH$;gSP{j=pmz%l>7z9`Y395AaGaFpAcBLfeL}sBGr0L zQJ#96zOlj}&koM#g7-jZgPoy<%3h)k^XCYs&+kHC-k)IXdf&$HC*Gue1Gi5AeX=qG z=yN)K2o*bZfGbk8c-BGUA@CtL;9vY;^5?Xo&Os;y@TTNIS1(Tnn?5lc|*0?XSxSfbKG6WD2R@* zwe)BOo4LC7bk|&)c{MB0tU$8@%?dOtkgWp$0Fi>@@?9+uL;wH)07*qoM6N<$f|%CE ACjbBd literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..aac582f18fc2684867c5c4035acbc814e889a523 GIT binary patch literal 1740 zcmV;-1~d7IP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS>Hc3Q5RCodHo8OC7RTRf(Boi&{ zhh=iWIB*6g#_UO&Hce(bZ)z9SKAIIy!omwkE)tfPaDGbc4=^@UkV15CCk3|AIp_!@$x6iNf1~<3L+_ zAmspO>46l1bH!EewMXcOF1g`9lOk|Z0mz~=lsE1?h3C;73b3MrLzk6#>9hgqqbdSZ zXrib>DdubVZlkCx$Tl-6{LL5}NwNJG{fYQw65Z#KJq0hfd?9PVbMSfi6t=Up{iQZ% z0mDtYz~6^LnKBld4!rGb(9xta4{0KL6yD-|^t>gw3JYCU3?(QC5?ae(J>7iTqoNQl zhyU>hGxl$xHwCZgDL@1a{nwTE@A_j<3rOe)oEbw`qE|WqkaK;AgWk;836utoioFB= z2DWGcBnH#K(Yu>oaGS(&-b>7iJ>~orZQI_YiJEpp{)E6gxjE{zUdi!M_&Fn)Kap*P zKY(8|#&u(V7C)!sWB6=$la~5@u=E~L$DkMSd(4oR7YQ6VbrKklB9P$FnKa9oMe?tI zLMg&W=#0C>*qTz#En_7OX9malz$OhOh7;5gaAL9FOL$-G9CkV#Y4KYK92Xq>EFg6h zoLKB*i?}3?b~v3NP1bcNtE8MmA8F zl>;W;Qo}x@Hi`Dd^-_;fUTZk{GSw&=#I6$eoKUXhw*uA~xS*R0Y@wj1iz>UXS^ac(bmp{3W!$nN)P5cosmcs03h{;#iCUUSw_d#!>sXHJP4#^GEqtEtW-P!dh5L4^k? zLaPv=w}s}elHBPhkcm3Eom9kt^ouW;g=!cUfT*L~lIt)71UTgv?S~wo@}GT%6(G)@ zN!XfDp3#{VsynkBCoPoOxX+3t-q}yjRy_pyy9J>}<4#MrYBKVkF>;rv*yaVRK%AX3 zf;?&IR!K(Aq3tgx80*{$2F|oG+o!!%0>jURWXE7@8&CNSR7S8je01nvhxI$uN)ow+ zw&1wUrUtV!?WPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS>Q%OWYRCodHn_Y-iRTRg)=0{mc zX=#I%R1k$UAwklIO+8fDLlKEoi1TK>*8wh~sYRH-ovZKB3&CZ3G+z zU%+=Vp>O^s0_!zSneWjp$j|z(B^>92VS|5-%T4<>qfZu<9w_gD)h=%-Wk|0#BGC=? z%AyY7SOQKN{5n%6gtochFQZQ$)me-N!2F26@DZ|k;3weArzmC@ae)1xPfA@6g9{^G z%4H@fa<_*ywrzUmGP=V(Wk1ML~@M&l$dWl8c?s35PleIo^la>*z z7jYN{SE%mDIOSE`01rC4U=hB{==2R(>~;Qy`U?1ToFv#}y-Cad5+J*4RWal~eC;#z z*;NF1C(z8-m%}K|&B93kcYTspeQg$=w0+@@I|Fs=@PDMVv{U;*w!JkF|M2qE-nItA z^}cbdzT37aM~jaqWBd-5;{g^N=!SjJaHOZhJt0T*=>fkQ_9xNla;Q}BvCr@=Rex!Y zAzJ~g$L?|TiKi>=nu}QSU}*s+5aC!q(1;Ph@94@~EJL=*a3a-Paq-diXpGI9aW+-x ziD7L_97E{KdGtfn03R5R^i(s2zHb}-b(36V8dRvnr?yut*;1NY*q0d|&c->QuO?@{ zY>ew)rJf)bf*<@~sE>i(w7x^9+wrtS3H?qbv{lx`+-DSW-I)C!bRN1lNK&e$NGL&- z4PZKmNzxF0tl9Jp=(nYbVMZsYm4IhBer+UUGiOnsp`WCh@d@HA8e_!T=Jg*g8oO@f z3nyj7tArBt-&)PH>#8bA(i&4|k}sMU?eLXuJ(QrP+quijFB1QLV+Kpbd)J$c2()~9)zF7k zB;o+Dal*K??#_&* z-x-fv%>MS(wT{Z|9$*pwjA1#@>mOeR)e{XmxRKCjgCUKWoVD;xKVIkW7(8gAQsW@KRnqCk_cGe@w{`dqasv z9nwhLuN$#TRqDqJM+_%7bx00k!yx9k&tE>HEz=fHtP?drW_=8`J<+Jmjl|poG&A<4 z+z+T)3DQQqFXJd~Y;zuB-4k2fCwO`%R<7V|DX>1pJB0qya=jI2Bc`~IIQJB1k72-R z+*hwZ)0S@y6XUChnpm`NWl5pWfP)_=;PGMtKLq>_%%kz>A3OVj{%Lb2QcmNs(htdl z3DQ7G(n<~oKu7E-DyEe35-$!mr|fHXOO+s5lBByh=vrQ+dKbtbF|H#)`esd8K^T*XQ0kNoq;+72^shYjGR0=(3V}e00000 LNkvXXu0mjfpC3Fo literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png new file mode 100644 index 0000000000000000000000000000000000000000..df8bb0f1d3286c2db794e11b7e5fc986b1060e9d GIT binary patch literal 1418 zcmV;51$Fv~P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS<^hrcPRCodHn>%O~K@^5_MZ_11 zf=U!C5fo7gRyHaGn;20rAQpmJ_^1VKEJ6w;K5C7Hfe1nfq_I|vScoY?Dql!!jHoDx z0plZy--){+&Yrz@cJJ)tu6y7xJLk@v^Pm6D?#%3?si~Bbfs%oef$SKl*oK~&nORBO zqh9;|N~QAEwr}Cv2|4H+)E7Ax!b%YaAmg;p%)IjS|G>@y%Ouw;?KGRxtg%hD1T}V+ zb)YW^szKhu8owve9PdY$ItVa@k8yMiea7rM;lSsdi_{5%oDQP*qe+b33H;x~ z_jQPRJ(p!22T6de1?K_{l8U<=-!i+7K-3A!x@C3*;mltIhRsa-lt}yN*QwaWBtt&S z#pE*L_kypPk#t1>#TFq4oxcdA>O|DVB%V9aDJKzXJCQgCW0OP23JzpQ_SEB~O5Zd5 zgSXA!iRtnpEvM^7^Z>fXj79wmx&<7cl;3Kbgdj925%NeVjNd;jU#)HFo>kzwdS>GruBtb$7Bt56-mSaQqP(NwdLaT)($jkULrM4%##wgO(OaY<_ zO^`QZoeO0BcZR#6*aIe8f@In@MYEZ0GOt6@13=tWfE;HO#abH$eBsDkOse~=K*yXI zPb;cPpLKflZb9FAUZj+}fSC(8+R*nNF29g^TNH4#@AEqw<#sDSbQ(4~ z4qJ6hun~B+p_2wKzbf`^w&7_Twl=zB- zJ1ZYbN4bTNseox*!!^$qY5POJ73i;d{pD~PUE(KdyBG7@|954h5%jdiKUC{?v->d& z=HvJGY;eDu4Fh#!*v(c0jZ!uMB3Bpb07ohFp@sugZl?KM5+tkvEEfyK+!CY?ElVRw zx!Gz2*uh|lA=k}F!_8*3hy;<7yW1T_BZz$5-Y_d5L2hrk7KtEo3EP;)ziD4Eg2HZX z#DDBl6oSa3{+nakyj%o=$idB;r@#ccS@VPt^i3H>@*Z+S2-w}Nd9;iP@KPaYm)16K zHgG#z^HjSZ^h!zG|Kd>jDOV5L{hCLE zPoQ<^chrbajC>bajC>baj$RPuN Y04sPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?CP_p=RCodHn`?+wRTRf(932(2 zEd0=m9+(z0U{6J&gr=GgA~l*773oCH2tCB2n&?Z}ljuWVG7v?nW}pW}(}xU%A|s4Q zQhS$VO=M9HjSqaJ&h%R|_g?p`v-Zq6=k9ywj-Ca7?p|x}^*H}~_Bs2!s;V-{7|0mN z7|0mN7|0mN7&tK*s7|xleSLkC@v8%8f~g=?9Q;DaQG)ydeg!{OS6BD)8%$zv7^KM9 zn?WTpa%O`s!Dx}cD0E&~2qMv);NWOsM%CF;EJ;I7F(HQp zuN9kQ1pSYYdmhtmL)sd=1VPShf^G!kjo|yReF(OIU7!z)l+=*;Y|sSc#GyrwMfE|C zNsv^knCWAvN!Cv%=oL1HbQ|olFUu}b^9oG0nHiFDC0>70gNCgaL z8y+&YLrgamRUQEr7=a%zD(DC}vkfxUHW}Np6WghAOB!Pglxr(3-P%y;dhVL+F6um} zYCQw}C1vxf7D3k9D9Ad8e{Kqx4;sNK-l_t1K++F{dcp{|g#76)MR05dT3U@HiA)4s z1bUpnf770yC`gLIAT*Vz7fWv3>+v z8Zn#&4yz8ik0V8vMacEE$}eg!m^)+v3*T%k(t@v<}k?M4i-#acEn z?h0_kh_TE`HMq&(q6s3#M6laPJj2aK|2AXHJ?pSI)heBR0Vm9>%F z>y8Q?Aqcv|NtSPZrnAw}lJ9hWx9D+NXRJ)C;Uv~{Bgl9lQ(udmStDl{T}xVB&JtSI zX#;u(=u!5Isq`vk)9M^;F!VTMsyM41!dK3$TBeIZpMv$E#5x-%E7NO~;{o)@T}g`D zkA1BgE9wJ=t(2x}U+~}rkw`8Zbli6#V~?kZmDqb#-$IC%7bAS~xv#^q#~C9BdwK46 zqvMxv{wxi>A^FZ?ey!^&d5k2t8zLal_eQd@*p?dheiLNNC4)>)pLFEL`1)P@3KUuK zyV8ZS-8B^2Y((mVG`?4ZP$G|MY72#_27Mt;^RtLkzSBI()`F07yW%CHlB}48;x|UI zrCBJFXcCa;XCY-%gpoi7ihRZ>G;*mSb3K&YM4*#YFnP&ghqC!pS(r@&a?s3+Jfpju zK(uAFs(67TZJ&--E-|v4i9X5-c%6;)~w} z;5PZq$13KRIP#89(ea2;15!VF4z>t#r_M%6z;Ce!zi;{L$2LQ zj@^cRkjXj*^$i*^py*?aF{JWL>^T=v)e57sS0QJ;VUL(Bf_6nl4SbJbm@C%=IkIhX z)^b81xM(7LO*l)a}Xb@4ENJiNp?gYB?h;%rY%jO$47 z4}g|VcTAObX3zk1cZ(rQUc9Ua z@>>5?kSY#-Aw)h4m(~9c5d5?75Cvv2G6pgRG6pgRG6pgRG6qH?1OEd8_oRFd1hyvt O0000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=%}GQ-RCodHn>~nKMHI*1Gh(xn z*d#F~D2P@OEH;aUjV`!_Vi6)1nnopvNvVafBm_c4!HBI0DFQK=M$|4rC4~{978W*1 zwF@R{W4^?%B%9wqd*5Ss-kCf1W9II=&wJo--<&z~pL6~@ckbM|v%Ov?9RnQ$9RnQ$ zW6MB)Tq0XqTG~o1&!7*X4`j-vcQMliuBZF`{x35AF9cFHq4VfD^cETt`N&soHcc!^ zBsYcbN3Wt)MQw#KHBm&7&@6fhjU~dGod}XhWH0((EM`{V2y<_%Ng{y{RwR`7^Cp!S z(H}C^Z`q2-kyesKX8Qu!{X_jRbSFA8r^uGo$w$6&!cDSnS(u)_=Idf7Yfr#>C2&QzL*WUz zXmG+rty}F}QH)0Y2zD!Ky;~hi6$t%l3E+xi&`WS-xvO%^{DyN>TRR1xQ0p&g;8~_EhS7?}aI;OR2(pIyW*)i8-j6cu z%|@D5EQXtHN=49u(VhC5GwiWU!nX3UVu{sfH5@I@(1}#}7glRY($h^#0N-aJB^Q$6@fRHTpp!+C<}H$nc7Q4sN!A8akvTWI z4++*jf+vy)>?735OB-jevo-s1^x)eBm}(@oiGyIQ9Z5lo?#ypdCT{CqHM{4pBHw9r z2Hl8O-72|G+eP#Y^MUo5hN?Ky*qlU1+ff~fiz!+$e}O&{hYlMB{3s*IM#oAAuc3dV zspKz!cXZU{)RdeclAJ-mMXzPonUxtr z(n-qJ|5)6QJ^8J+GL}-mN#-Ex%E2-qG~R;#;ee>T>X-`Ub?DcQpNe|)*M2CJiP`l{ zJ%XO6!~2|0RhE4yj3Ui#FQYex#^oOyxLC^p$1PnkH9>_Vha??z`pIZe>ky`aSIU%{ zpf8E$vJ;WYvab?uCEa$9uQDzd77SZsrlbUAqe2Ip&Z5_|>s)3ZCJ8xuY8^-K9vYW_ zXeqGh*cvUm0Y&c|GW5FgWB~X*>aBIphqSMC2s6-cusZ1o3igfzqvu5~ZyLV8Vte1P zH)>i_f*@x**&a1A)>G{zMvrdGHI+PqtYiI}E20SG=n<~}ub46b--euT4Ey+)NMK^$ z=F70`U8O?M4uB?ZKd1~j^35Yibs}h5jtz(&=`-9~7aHg*P8W`wpy literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png new file mode 100644 index 0000000000000000000000000000000000000000..90751e1696cb4218368578420f098ad41c3fce24 GIT binary patch literal 1574 zcmZ`(c{~#e9N%piZ7avf$Rp29=*fC&8aB;FQ6e?USP^A&Jx5!GiW)f@Tc%@37SZvc zazrG08&X>-dTyp;a+P{~KJWA1U+<6a_4|GQ{+{)rcxtHWsQ~~04HA*CYek8xfWubU zUs3D1BEZ;Po^Al~i}e#Lfe;ozqI-J-ELJ=m0L)+jAgh%X=&b+%01JTt@QMOgZ$i+& zU!oBFpIYf6rTyHU4t*Y7_IdW(lfaC-?L4R2 z`TFUREz0JS-<926^C`-Mu|c(QRBB$w_QOV-keEya0cH%&VgD0#_ad^gvfjeqfxk5y zy@nTLS)wBaXHGBD9AcieuiGDT6enUalUxEcD8LfFs0Ak3CL;NcjSmxIY@H$U{6@wn zgmW4h?cQE+azI$VzP0IuT_PFj?l}swZVG!IuFK!8LwXd3GhT3wbVba7cdNbLMtO6) zc?J>pb#4x8MXObaZlECccUWc#YWw>DW3LmYy?Rb@?R(M%UN;Neki%9R>-}jt zW}WYUrK%ED7h%SfB)LG)hIG(>s2cgj(5p)4B4?@@>OYHaxYR_pd!+WwKxT5eV!OdM zP4bqrp;{5)MbI{OcWU*zTYw}xxxr6p#k9%squiRC7O1AE!FEUEzv6L=Eh@N3GWZox zAUFVf)8vb^u&kVH?6t{Zym?o&b||n@?sBc%H2^*Xpq}y`H1kP+`*E5qgAyu3mcuE1 z(F@5vbLbd{1o%T}*97~fpR}^`q^-DR#Cacr`8NKncIZ?G{LGOpz zxk8hRdmR*hg~bXfWAY()q#` z%?K`xgdA-yWT&!t^KP`@c&C8=LTK^ZsC!p?T!Y%qvHqyu=Af^>2td{bW%uav z-#C70P|4Rab9FK_F_`nxT(9PNfbE*Yg50#i@0a!oeyRE~rs(@&jR|iICA=yZ@jsu# zpQ%@sQoi9p4dk3t<+Eeycu>R!TKb$%uYWT@q1TU4xgr(Ia*$h{0sb2R&Lvv;&xWj{neQGex`ITwFc8*ZCD4xXc%rtbCllA5)$^#Q|PC4@|H8D%2;Ce zJ=KEH z1sBj=X4oS#v%iwMhry%gEnh%ErG7G`*98{|3V$T?(wYUS`c*~tgBc~)O)YqoNfDHCpxp=n*sD|ek47Wk+VzBC?|vE%Fh=pp3HmGRavQ-~@1;Q(p7R-G)p zTR$Np16MO3#oM={R6K%rj8_uVh|9T?5rI>Zn@&ES+1)giVdnQ;ffzhQM8&`Qq%^;b z=qw2Q@iD+09}3Am_QA8ain^#tP@lpIeeKme+^y48#C#(Zh!ne+sA&bZDJjCfXZxaw zM~e_zJmWfB6ERI4!*WV5m*rVQl_wuB8-fDM2%QHqB`=Tt-vo{!zOQMw`6-$EP$FI3 NXp%dHAa + + Filled / premium_object_check + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_star.svg b/TMessagesProj/src/main/res/raw/premium_object_star.svg new file mode 100644 index 000000000..66af2c02d --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_star.svg @@ -0,0 +1,7 @@ + + + Filled / filled_stories_closefriends + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_tag.svg b/TMessagesProj/src/main/res/raw/premium_object_tag.svg new file mode 100644 index 000000000..fbf6bbf32 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_tag.svg @@ -0,0 +1,7 @@ + + + Filled / premium_object_tag + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/tag_icon_3.json b/TMessagesProj/src/main/res/raw/tag_icon_3.json new file mode 100644 index 000000000..5e044579e --- /dev/null +++ b/TMessagesProj/src/main/res/raw/tag_icon_3.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":57,"w":512,"h":512,"nm":"TAG ICON 3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Tag Body","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[-106]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":16,"s":[25]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":27,"s":[-13]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":37,"s":[8]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":47,"s":[-4]},{"t":56,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.7,"y":0.931},"o":{"x":0.3,"y":0},"t":0,"s":[254,408,0],"to":[-74.5,-134.5,0],"ti":[-49.225,2.261,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0.089},"t":14,"s":[286,158.5,0],"to":[40.849,-1.876,0],"ti":[57,-60.25,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":25,"s":[315,296,0],"to":[0,-3,0],"ti":[0,0,0]},{"i":{"x":0.71,"y":1},"o":{"x":0.3,"y":0},"t":35,"s":[320,229,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.71,"y":1},"o":{"x":0.29,"y":0},"t":45,"s":[320,267,0],"to":[0,0,0],"ti":[0,0,0]},{"t":54,"s":[320,256,0]}]},"a":{"a":0,"k":[64,0,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[-0.126,0],[0,17.396],[0.126,0],[0,-17.396]],"o":[[0.126,0],[0,-17.396],[-0.126,0],[0,17.396]],"v":[[20.869,31.498],[21.098,0],[20.869,-31.498],[20.64,0]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[17.198,-1.425],[-3.426,10.9],[-19.312,-0.892],[5.119,-7.228]],"o":[[-18.295,1.516],[3.427,-10.901],[18.317,0.846],[-3.491,10.891]],"v":[[40.158,-8.836],[10.481,-23.231],[49.943,-45.497],[77.084,-23.231]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.2,"y":0},"t":12,"s":[{"i":[[21.564,0],[-4.006,7.942],[-22.639,-1.298],[4.67,-9.069]],"o":[[-21.564,0],[4.007,-7.944],[21.477,1.231],[-4.083,7.928]],"v":[[63.815,-7.069],[35.545,-23.661],[85.502,-39.932],[113.636,-23.661]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[21.053,2.96],[-4.407,11.239],[-21.674,-3.949],[3.263,-12.53]],"o":[[-21.053,-2.96],[4.407,-11.24],[20.873,3.803],[-2.852,11.733]],"v":[[61.756,2.568],[34.266,-24.33],[83.08,-40.272],[109.731,-16.531]],"c":true}]},{"t":30,"s":[{"i":[[20.556,0],[0,20.556],[-20.556,0],[0,-20.556]],"o":[[-20.556,0],[0,-20.556],[20.556,0],[0,20.556]],"v":[[63.457,37.22],[26.237,0],[63.457,-37.22],[100.678,0]],"c":true}]}]},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0.724,9.912],[0,0],[1.951,0],[0,0],[0.289,-28.314],[0,0],[-4.286,0],[0,0],[-0.907,13.68],[0,0]],"o":[[0,0],[-0.907,-13.68],[0,0],[-4.286,0],[0,0],[0,33.937],[0,0],[1.951,0],[0,0],[0.229,-10.345]],"v":[[27.834,-16.955],[26.33,-95.483],[21.682,-117.732],[3.261,-117.732],[-1.844,-55.875],[-0.983,55.649],[3.261,117.732],[21.682,117.732],[26.33,95.483],[27.807,15.958]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[4.878,7.791],[0,0],[13.154,0],[56.635,-35.52],[6.841,-25.27],[0,0],[-15.807,9.603],[0,0],[-8.9,8.588],[0,0]],"o":[[0,0],[-6.113,-10.752],[0,0],[-26.801,16.809],[0,0],[-2.437,22.407],[60.444,-36.722],[12.619,3.715],[0,0],[4.723,-7.926]],"v":[[123.359,-30.426],[91.131,-74.085],[59.796,-91.572],[-55.408,-67.096],[-100.621,-13.95],[-114.411,88.552],[-80.707,105.6],[36.254,74.326],[71.252,66.401],[123.789,-8.485]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.2,"y":0},"t":12,"s":[{"i":[[6.77,6.825],[0,0],[18.256,0],[0,0],[13.655,-22.627],[0,0],[-40.102,0],[0,0],[-8.483,9.419],[0,0]],"o":[[0,0],[-8.483,-9.419],[0,0],[-40.102,0],[0,0],[-6.973,16.6],[0,0],[18.256,0],[0,0],[6.77,-6.825]],"v":[[168.176,-24.368],[120.641,-64.341],[77.153,-79.659],[-61.02,-74.059],[-133.415,-40.227],[-191.355,39.253],[-147.896,79.128],[48.666,67.592],[92.154,52.273],[168.814,-7.424]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[6.77,8.194],[0,0],[18.256,0],[67.028,27.809],[11.511,-18.917],[0,0],[-26.572,-13.524],[0,0],[-10.604,10.629],[0,0]],"o":[[0,0],[-8.483,-11.308],[0,0],[-31.083,-12.896],[0,0],[-9.627,21.678],[76.682,39.029],[13.562,-2.257],[0,0],[6.77,-8.194]],"v":[[157.925,-31.952],[118.936,-77.921],[79.796,-91.72],[-60.502,-94.635],[-116.892,-86.389],[-167.855,14.804],[-131.338,78.953],[54.126,97.567],[96.347,76.456],[158.384,-9.149]],"c":true}]},{"t":30,"s":[{"i":[[6.77,11.713],[0,0],[18.256,0],[0,0],[0,-40.102],[0,0],[-40.102,0],[0,0],[-8.483,16.165],[0,0]],"o":[[0,0],[-8.483,-16.165],[0,0],[-40.102,0],[0,0],[0,40.102],[0,0],[18.256,0],[0,0],[6.77,-11.713]],"v":[[168.822,-18.931],[114.552,-112.828],[71.064,-139.119],[-101.289,-139.119],[-173.899,-66.508],[-173.899,66.508],[-101.289,139.119],[71.064,139.119],[114.552,112.828],[168.822,18.931]],"c":true}]}]},"nm":"Path 2","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":1,"op":180,"st":0,"bm":0}]} \ 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 e34908aee..489fc24e5 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -161,6 +161,7 @@ yesterday No results No results found for \"%s\". + No results found for %s Welcome to Telegram Recently viewed HIDE @@ -3141,6 +3142,10 @@ Save to gallery %1$d of %2$d **%1$d** of %2$d + %1$d message + %1$d messages + Show as List + Show as Chat Gallery All photos All media @@ -3529,7 +3534,7 @@ My Contacts (-%1$d, +%2$d) Nobody (+%1$d) Everybody - My Contacts and Premium + Contacts & Premium My Contacts Nobody Everybody (-%1$d) @@ -3744,8 +3749,8 @@ Rental Agreement Phone Number Email Address - This message is not supported on your version of Telegram. Update the app to view: https://telegram.org/update - This message is not supported on your version of Telegram. Update the app to view: https://telegram.org/dl + This message is not supported on your version of Telegram. Please update to the latest version. + Your version is up to date. Photo Video Self-Destructing Photo @@ -5308,8 +5313,12 @@ Switch to day theme Close Trending stickers Close Trending emoji + Edit Message Tag Play Pause + Resume + Activate Play Once + Deactivate Play Once Download Cancel download Open file @@ -5755,6 +5764,7 @@ Quick Reactions Double tap this message for a quck reaction. un1 changed chat reactions \nfrom: %1$s \nto: %2$s + un1 changed chat reactions:\n %1$s Nobody viewed QR Code @@ -5938,6 +5948,10 @@ Subscribe to Telegram Premium to download media and files at the fastest possible speed. No Ads No more ads in public channels where Telegram sometimes shows ads. + Tags for Messages + Organize your Saved Messages with tags\nfor quicker access. + Tags in Saved Messages + Organize your Saved Messages with tags for quicker access. Unique Reactions Premium Stickers Exclusive enlarged stickers featuring additional effects, updated monthly. @@ -6201,6 +6215,8 @@ Close topics Reopen topics All Topics + View as Chats + View as Messages View as topics Are you sure you want delete these topics? Are you sure you want delete %s? @@ -7272,6 +7288,8 @@ Get more views as your stories are always displayed first. Stealth Mode Hide the fact that you viewed other people’s stories. + Higher quality + View video stories in double the resolution. Permanent Views History Check who opens your stories — even after they expire. Expiration Durations @@ -7977,14 +7995,18 @@ Message reposted to your profile. Message reposted to **%s**. Select Wallpaper - Saved Messages + Saved Chats %d chat %d chats %d saved message %d saved messages Author Hidden - Unsave messages from %s + Delete all your notes + Are you sure you want to delete all your notes? + Delete all your saved messages + Are you sure you want to delete all your saved messages? + Unsave messages Unsave messages from %d chats Are you sure you want to unsave messages from %s? Are you sure you want to unsave messages from %d chats? @@ -8013,10 +8035,14 @@ Hide the time when you read messages from people who can’t see your last seen. If you turn this on, their read time will also be hidden from you.\nThis setting does not affect group chats. read show when - read %s + read today at %s + read yesterday at %s + read %1$s at %2$s read time unknown Subscribe to Telegram Premium If you subscribe to Premium, you will see other users’ last seen and read time even if you hid yours from them (unless they specifically restricted it). + Subscribed to Telegram Premium + Because you are a Telegram Premium subscriber, you will see the last seen and read time of all users who are sharing it with you – even if you are hiding yours. Show Your Read Date To see when **%s** read the message, either start showing your own read time... To see when **%s** read the message, start showing your own read time. @@ -8037,7 +8063,7 @@ Your read times are now visible. Premium Required Subscribe to **Telegram Premium** to select this option. - Unlock + Subscribe Subscribe to **Premium** to message **%s**. **%s** restricted messaging to only Premium users. Get Premium @@ -8051,10 +8077,42 @@ Show Other Messages Hide Other Messages **%s** only accepts messages from contacts and Premium users. + Remove Tag + Add Name + Edit Name + Name + Add Tags + to your Saved Messages + You can label your emoji tag with a text name. + Filter by Tag + Search messages or tags + Tap this icon to search by tags + Tap and hold to add a name to your tag + You can add a tag to the message + Tag the message with an emoji for quick search + Organize your Saved Messages with tags\nfor quicker access. **Learn more…** + Message tagged with + Messages tagged with View Replies restricted Unlock You need a **Premium** Subscription to reply to **%s**’s stories. Unable to send Only Premium users can message %s + No messages under this tag or search found + Add a tag to selected messages + Edit tags of selected messages + Increase Quality + Quality Increased + You can lower the quality later for faster downloads. + Lower Quality + Quality Lowered + Stories will now download faster. + High-Quality Stories + Subscribe to Premium to view stories in higher resolution. + Messages you sent to Saved Messages + Last Seen Times + View the last seen and read times of others even if you hide yours. + Message Privacy + Restrict people you don\'t know from sending you messages. diff --git a/gradle.properties b/gradle.properties index b6ea21465..7f4dade33 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=4275 -APP_VERSION_NAME=10.6.1 +APP_VERSION_CODE=4365 +APP_VERSION_NAME=10.6.4 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=android RELEASE_KEY_ALIAS=androidkey