From aaa5dc0328e40aa46aac73edb3d1d54e061a2d59 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 30 Oct 2020 13:26:29 +0300 Subject: [PATCH 1/2] Update to 7.2.0 (2128) --- Dockerfile | 2 +- TMessagesProj/build.gradle | 25 +- TMessagesProj/jni/CMakeLists.txt | 2 +- TMessagesProj/jni/TgNetWrapper.cpp | 5 + TMessagesProj/jni/lottie.cpp | 7 +- TMessagesProj/jni/rlottie/inc/rlottie.h | 2 +- .../rlottie/src/lottie/lottieanimation.cpp | 10 +- .../jni/rlottie/src/lottie/lottieitem.cpp | 10 +- .../jni/rlottie/src/lottie/lottieitem.h | 2 +- .../jni/rlottie/src/vector/vpainter.cpp | 10 +- .../jni/rlottie/src/vector/vpainter.h | 4 +- .../jni/tgnet/ConnectionsManager.cpp | 7 +- TMessagesProj/jni/tgnet/ConnectionsManager.h | 1 + TMessagesProj/src/main/AndroidManifest.xml | 2 +- TMessagesProj/src/main/assets/arctic.attheme | 4 +- .../src/main/assets/bluebubbles.attheme | 2 +- .../src/main/assets/darkblue.attheme | 58 +- TMessagesProj/src/main/assets/day.attheme | 5 +- TMessagesProj/src/main/assets/night.attheme | 51 +- .../widget/ChatListItemAnimator.java | 33 +- .../recyclerview/widget/ChildHelper.java | 3 - .../widget/LinearLayoutManager.java | 70 +- .../widget/OrientationHelper.java | 5 +- .../recyclerview/widget/RecyclerView.java | 36 +- .../telegram/messenger/AndroidUtilities.java | 40 +- .../org/telegram/messenger/BuildVars.java | 4 +- .../org/telegram/messenger/ChatObject.java | 4 +- .../messenger/DownloadController.java | 8 +- .../org/telegram/messenger/EmojiData.java | 4 + .../org/telegram/messenger/EmuDetector.java | 76 +- .../telegram/messenger/FileLoadOperation.java | 66 +- .../org/telegram/messenger/FileLoader.java | 163 +- .../telegram/messenger/FileRefController.java | 6 +- .../messenger/FileUploadOperation.java | 3 - .../messenger/GcmPushListenerService.java | 214 +- .../org/telegram/messenger/ImageLoader.java | 47 +- .../org/telegram/messenger/ImageReceiver.java | 32 +- .../telegram/messenger/LocaleController.java | 165 +- .../messenger/LocationController.java | 76 +- .../messenger/LocationSharingService.java | 10 +- .../telegram/messenger/MediaController.java | 339 +- .../messenger/MediaDataController.java | 230 +- .../org/telegram/messenger/MessageObject.java | 209 +- .../messenger/MessagesController.java | 638 ++- .../telegram/messenger/MessagesStorage.java | 461 +- .../org/telegram/messenger/NativeLoader.java | 2 +- .../messenger/NotificationCenter.java | 46 +- .../messenger/NotificationsController.java | 169 +- .../messenger/SendMessagesHelper.java | 371 +- .../messenger/video/TextureRenderer.java | 2 +- .../telegram/tgnet/ConnectionsManager.java | 8 + .../main/java/org/telegram/tgnet/TLRPC.java | 659 ++- .../ui/ActionBar/ActionBarLayout.java | 13 +- .../ui/ActionBar/ActionBarMenuItem.java | 7 +- .../ui/ActionBar/ActionBarPopupWindow.java | 64 +- .../ui/ActionBar/AdjustPanLayoutHelper.java | 7 +- .../telegram/ui/ActionBar/AlertDialog.java | 17 + .../telegram/ui/ActionBar/BaseFragment.java | 5 + .../telegram/ui/ActionBar/BottomSheet.java | 13 +- .../telegram/ui/ActionBar/SimpleTextView.java | 2 +- .../java/org/telegram/ui/ActionBar/Theme.java | 147 +- .../ui/ActionBar/ThemeDescription.java | 4 + .../ui/Adapters/DialogsSearchAdapter.java | 19 +- .../ui/Adapters/DrawerLayoutAdapter.java | 10 + .../org/telegram/ui/Adapters/FiltersView.java | 9 + .../ui/Adapters/LocationActivityAdapter.java | 27 +- .../telegram/ui/Adapters/MentionsAdapter.java | 138 +- .../telegram/ui/Adapters/SearchAdapter.java | 3 +- .../ui/Adapters/SearchAdapterHelper.java | 12 +- .../ui/Adapters/StickersSearchAdapter.java | 5 +- .../java/org/telegram/ui/ArticleViewer.java | 10 +- .../org/telegram/ui/Cells/AboutLinkCell.java | 4 +- .../telegram/ui/Cells/ChatMessageCell.java | 2003 +++++--- .../org/telegram/ui/Cells/DialogCell.java | 253 +- .../telegram/ui/Cells/DrawerProfileCell.java | 2 +- .../org/telegram/ui/Cells/MentionCell.java | 23 + .../telegram/ui/Cells/SendLocationCell.java | 1 + .../telegram/ui/Cells/SharedAudioCell.java | 2 +- .../telegram/ui/Cells/SharedDocumentCell.java | 2 +- .../org/telegram/ui/Cells/SharedLinkCell.java | 2 +- .../ui/Cells/TextSelectionHelper.java | 2 +- .../org/telegram/ui/ChangeBioActivity.java | 2 +- .../telegram/ui/ChannelAdminLogActivity.java | 12 +- .../org/telegram/ui/Charts/BaseChartView.java | 2 + .../java/org/telegram/ui/ChatActivity.java | 4552 +++++++++++------ .../org/telegram/ui/ChatEditActivity.java | 7 +- .../org/telegram/ui/ChatEditTypeActivity.java | 2 +- .../org/telegram/ui/ChatLinkActivity.java | 4 +- .../org/telegram/ui/ChatUsersActivity.java | 18 +- .../telegram/ui/Components/AlertsCreator.java | 100 +- .../ui/Components/AnimatedNumberLayout.java | 161 + .../ui/Components/AudioPlayerAlert.java | 525 +- .../org/telegram/ui/Components/Bulletin.java | 247 +- .../ui/Components/BulletinFactory.java | 165 +- .../ui/Components/ChatActivityEnterView.java | 91 +- .../ui/Components/ChatAttachAlert.java | 127 +- .../ChatAttachAlertAudioLayout.java | 8 +- .../ChatAttachAlertDocumentLayout.java | 6 +- .../ChatAttachAlertLocationLayout.java | 17 +- .../ChatAttachAlertPhotoLayout.java | 5 +- .../ui/Components/ChatAvatarContainer.java | 20 +- .../org/telegram/ui/Components/CheckBox2.java | 2 +- .../telegram/ui/Components/CheckBoxBase.java | 86 +- .../ui/Components/EllipsizeSpanAnimator.java | 2 - .../Components/FillLastGridLayoutManager.java | 9 +- .../ui/Components/FlickerLoadingView.java | 262 + .../ui/Components/FragmentContextView.java | 26 +- .../org/telegram/ui/Components/HintView.java | 23 +- .../ui/Components/MediaActionDrawable.java | 9 +- .../ui/Components/MsgClockDrawable.java | 85 + .../ui/Components/NumberTextView.java | 31 +- .../Components/Paint/Views/ColorPicker.java | 2 +- .../telegram/ui/Components/PathAnimator.java | 110 +- .../ui/Components/PhotoPaintView.java | 4 + .../ui/Components/PinnedLineView.java | 283 + .../ui/Components/PlayPauseDrawable.java | 115 + .../ui/Components/PlayingGameDrawable.java | 13 +- .../ui/Components/ProximitySheet.java | 651 +++ .../ui/Components/RLottieDrawable.java | 142 +- .../ui/Components/RadialProgress2.java | 77 +- .../ui/Components/RecordStatusDrawable.java | 28 +- .../RecyclerAnimationScrollHelper.java | 1 - .../ui/Components/RecyclerListView.java | 8 + .../ui/Components/RoundStatusDrawable.java | 21 +- .../telegram/ui/Components/SearchField.java | 1 + .../ui/Components/SearchViewPager.java | 39 +- .../telegram/ui/Components/SeekBarView.java | 54 +- .../ui/Components/SendingFileDrawable.java | 30 +- .../telegram/ui/Components/ShareAlert.java | 19 +- .../ui/Components/SharedMediaLayout.java | 175 +- .../telegram/ui/Components/SlotsDrawable.java | 432 ++ .../ui/Components/StatusDrawable.java | 2 + .../org/telegram/ui/Components/SvgHelper.java | 229 +- .../ui/Components/TrendingStickersAlert.java | 24 +- .../ui/Components/TrendingStickersLayout.java | 40 +- .../ui/Components/TypingDotsDrawable.java | 31 +- .../telegram/ui/Components/VideoPlayer.java | 17 +- .../ui/Components/voip/VoIPToggleButton.java | 4 +- .../java/org/telegram/ui/DialogsActivity.java | 15 +- .../org/telegram/ui/FilteredSearchView.java | 268 +- .../org/telegram/ui/ForwardsActivity.java | 407 -- .../org/telegram/ui/GroupCreateActivity.java | 51 +- .../telegram/ui/GroupCreateFinalActivity.java | 1 - .../telegram/ui/GroupStickersActivity.java | 2 +- .../org/telegram/ui/LocationActivity.java | 630 ++- .../java/org/telegram/ui/MediaActivity.java | 2 +- .../telegram/ui/MessageStatisticActivity.java | 982 ++++ .../org/telegram/ui/PaymentFormActivity.java | 481 +- .../java/org/telegram/ui/PhotoViewer.java | 634 ++- .../ui/PopupNotificationActivity.java | 14 +- .../java/org/telegram/ui/ProfileActivity.java | 115 +- .../org/telegram/ui/SessionsActivity.java | 10 +- .../org/telegram/ui/StatisticActivity.java | 309 +- .../java/org/telegram/ui/ViewPagerFixed.java | 21 +- .../res/drawable-hdpi/blockpanel_shadow.png | Bin 0 -> 163 bytes .../googlepay_button_background_image.9.png | Bin 0 -> 979 bytes ...ay_button_no_shadow_background_image.9.png | Bin 0 -> 282 bytes .../main/res/drawable-hdpi/map_pin_arrow.png | Bin 0 -> 793 bytes .../main/res/drawable-hdpi/map_pin_circle.png | Bin 0 -> 529 bytes .../main/res/drawable-hdpi/map_pin_cone2.png | Bin 0 -> 2544 bytes .../main/res/drawable-hdpi/map_pin_photo.png | Bin 0 -> 3539 bytes .../res/drawable-hdpi/menu_bookmarks_hw.png | Bin 0 -> 1079 bytes .../res/drawable-hdpi/menu_broadcast_hw.png | Bin 0 -> 918 bytes .../main/res/drawable-hdpi/menu_calls_hw.png | Bin 0 -> 1074 bytes .../res/drawable-hdpi/menu_contacts_hw.png | Bin 0 -> 1112 bytes .../main/res/drawable-hdpi/menu_groups_hw.png | Bin 0 -> 1247 bytes .../main/res/drawable-hdpi/menu_help_hw.png | Bin 0 -> 1145 bytes .../main/res/drawable-hdpi/menu_invite_hw.png | Bin 0 -> 1055 bytes .../res/drawable-hdpi/menu_pinnedlist.png | Bin 0 -> 819 bytes .../main/res/drawable-hdpi/menu_secret_hw.png | Bin 0 -> 986 bytes .../res/drawable-hdpi/menu_settings_hw.png | Bin 0 -> 1332 bytes .../res/drawable-hdpi/msg_location_alert.png | Bin 0 -> 1169 bytes .../main/res/drawable-hdpi/msg_pin_mini.png | Bin 0 -> 399 bytes .../src/main/res/drawable-hdpi/msg_stats.png | Bin 551 -> 549 bytes .../res/drawable-mdpi/blockpanel_shadow.png | Bin 0 -> 157 bytes .../googlepay_button_background_image.9.png | Bin 0 -> 439 bytes ...ay_button_no_shadow_background_image.9.png | Bin 0 -> 174 bytes .../main/res/drawable-mdpi/map_pin_arrow.png | Bin 0 -> 562 bytes .../main/res/drawable-mdpi/map_pin_circle.png | Bin 0 -> 391 bytes .../main/res/drawable-mdpi/map_pin_cone2.png | Bin 0 -> 1539 bytes .../main/res/drawable-mdpi/map_pin_photo.png | Bin 0 -> 1908 bytes .../res/drawable-mdpi/menu_bookmarks_hw.png | Bin 0 -> 688 bytes .../res/drawable-mdpi/menu_broadcast_hw.png | Bin 0 -> 635 bytes .../main/res/drawable-mdpi/menu_calls_hw.png | Bin 0 -> 689 bytes .../res/drawable-mdpi/menu_contacts_hw.png | Bin 0 -> 811 bytes .../main/res/drawable-mdpi/menu_groups_hw.png | Bin 0 -> 797 bytes .../main/res/drawable-mdpi/menu_help_hw.png | Bin 0 -> 704 bytes .../main/res/drawable-mdpi/menu_invite_hw.png | Bin 0 -> 681 bytes .../res/drawable-mdpi/menu_pinnedlist.png | Bin 0 -> 604 bytes .../main/res/drawable-mdpi/menu_secret_hw.png | Bin 0 -> 632 bytes .../res/drawable-mdpi/menu_settings_hw.png | Bin 0 -> 910 bytes .../res/drawable-mdpi/msg_location_alert.png | Bin 0 -> 793 bytes .../main/res/drawable-mdpi/msg_pin_mini.png | Bin 0 -> 323 bytes .../src/main/res/drawable-mdpi/msg_stats.png | Bin 374 -> 443 bytes .../googlepay_button_background.xml | 7 + .../googlepay_button_no_shadow_background.xml | 7 + .../res/drawable-xhdpi/blockpanel_shadow.png | Bin 0 -> 168 bytes .../googlepay_button_background_image.9.png | Bin 0 -> 963 bytes ...ay_button_no_shadow_background_image.9.png | Bin 0 -> 263 bytes .../main/res/drawable-xhdpi/map_pin_arrow.png | Bin 0 -> 1025 bytes .../res/drawable-xhdpi/map_pin_circle.png | Bin 0 -> 676 bytes .../main/res/drawable-xhdpi/map_pin_cone2.png | Bin 0 -> 4129 bytes .../main/res/drawable-xhdpi/map_pin_photo.png | Bin 0 -> 5267 bytes .../res/drawable-xhdpi/menu_bookmarks_hw.png | Bin 0 -> 1582 bytes .../res/drawable-xhdpi/menu_broadcast_hw.png | Bin 0 -> 1299 bytes .../main/res/drawable-xhdpi/menu_calls_hw.png | Bin 0 -> 1535 bytes .../res/drawable-xhdpi/menu_contacts_hw.png | Bin 0 -> 1804 bytes .../res/drawable-xhdpi/menu_groups_hw.png | Bin 0 -> 1766 bytes .../main/res/drawable-xhdpi/menu_help_hw.png | Bin 0 -> 1549 bytes .../res/drawable-xhdpi/menu_invite_hw.png | Bin 0 -> 1443 bytes .../res/drawable-xhdpi/menu_pinnedlist.png | Bin 0 -> 1088 bytes .../res/drawable-xhdpi/menu_secret_hw.png | Bin 0 -> 1357 bytes .../res/drawable-xhdpi/menu_settings_hw.png | Bin 0 -> 2193 bytes .../res/drawable-xhdpi/msg_location_alert.png | Bin 0 -> 1627 bytes .../main/res/drawable-xhdpi/msg_pin_mini.png | Bin 0 -> 500 bytes .../src/main/res/drawable-xhdpi/msg_stats.png | Bin 711 -> 702 bytes .../res/drawable-xxhdpi/blockpanel_shadow.png | Bin 0 -> 172 bytes .../googlepay_button_background_image.9.png | Bin 0 -> 3186 bytes ...ay_button_no_shadow_background_image.9.png | Bin 0 -> 679 bytes .../res/drawable-xxhdpi/map_pin_arrow.png | Bin 0 -> 1543 bytes .../res/drawable-xxhdpi/map_pin_circle.png | Bin 0 -> 972 bytes .../res/drawable-xxhdpi/map_pin_cone2.png | Bin 0 -> 7475 bytes .../res/drawable-xxhdpi/map_pin_photo.png | Bin 0 -> 9638 bytes .../res/drawable-xxhdpi/menu_bookmarks_hw.png | Bin 0 -> 2651 bytes .../res/drawable-xxhdpi/menu_broadcast_hw.png | Bin 0 -> 1920 bytes .../res/drawable-xxhdpi/menu_calls_hw.png | Bin 0 -> 2342 bytes .../res/drawable-xxhdpi/menu_contacts_hw.png | Bin 0 -> 2854 bytes .../res/drawable-xxhdpi/menu_groups_hw.png | Bin 0 -> 2950 bytes .../main/res/drawable-xxhdpi/menu_help_hw.png | Bin 0 -> 2517 bytes .../res/drawable-xxhdpi/menu_invite_hw.png | Bin 0 -> 2341 bytes .../res/drawable-xxhdpi/menu_pinnedlist.png | Bin 0 -> 1364 bytes .../res/drawable-xxhdpi/menu_secret_hw.png | Bin 0 -> 2165 bytes .../res/drawable-xxhdpi/menu_settings_hw.png | Bin 0 -> 3659 bytes .../drawable-xxhdpi/msg_location_alert.png | Bin 0 -> 2347 bytes .../main/res/drawable-xxhdpi/msg_pin_mini.png | Bin 0 -> 707 bytes .../main/res/drawable-xxhdpi/msg_stats.png | Bin 1063 -> 950 bytes .../buy_with_googlepay_button_content.xml | 54 + .../drawable/googlepay_button_background.xml | 6 + .../res/drawable/googlepay_button_content.xml | 48 + .../googlepay_button_no_shadow_background.xml | 6 + .../res/drawable/googlepay_button_overlay.xml | 12 + TMessagesProj/src/main/res/raw/ic_admin.json | 1 + TMessagesProj/src/main/res/raw/ic_pin.json | 1 + TMessagesProj/src/main/res/raw/ic_unpin.json | 1 + .../src/main/res/raw/permission_map.svg | 12 + .../src/main/res/raw/permission_map_dark.svg | 12 + .../src/main/res/raw/permission_pin.svg | 9 + .../src/main/res/raw/permission_pin_dark.svg | 8 + .../src/main/res/raw/player_prev.json | 1 + TMessagesProj/src/main/res/values/strings.xml | 127 +- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 252 files changed, 15209 insertions(+), 5425 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedNumberLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/MsgClockDrawable.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/PinnedLineView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/PlayPauseDrawable.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ForwardsActivity.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/MessageStatisticActivity.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/blockpanel_shadow.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/map_pin_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/map_pin_circle.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/map_pin_cone2.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/map_pin_photo.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_calls_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_contacts_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_groups_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_help_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_invite_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_pinnedlist.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_secret_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_settings_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_pin_mini.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/blockpanel_shadow.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/googlepay_button_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/map_pin_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/map_pin_circle.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/map_pin_cone2.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/map_pin_photo.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_bookmarks_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_broadcast_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_calls_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_groups_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_help_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_invite_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_pinnedlist.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_secret_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_settings_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_pin_mini.png create mode 100644 TMessagesProj/src/main/res/drawable-v21/googlepay_button_background.xml create mode 100644 TMessagesProj/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/blockpanel_shadow.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/googlepay_button_no_shadow_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/map_pin_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/map_pin_circle.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/map_pin_cone2.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/map_pin_photo.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_broadcast_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_groups_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_help_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_pinnedlist.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_pin_mini.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/blockpanel_shadow.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_circle.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_cone2.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_photo.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_help_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_pinnedlist.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_hw.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin_mini.png create mode 100644 TMessagesProj/src/main/res/drawable/buy_with_googlepay_button_content.xml create mode 100644 TMessagesProj/src/main/res/drawable/googlepay_button_background.xml create mode 100644 TMessagesProj/src/main/res/drawable/googlepay_button_content.xml create mode 100644 TMessagesProj/src/main/res/drawable/googlepay_button_no_shadow_background.xml create mode 100644 TMessagesProj/src/main/res/drawable/googlepay_button_overlay.xml create mode 100644 TMessagesProj/src/main/res/raw/ic_admin.json create mode 100644 TMessagesProj/src/main/res/raw/ic_pin.json create mode 100644 TMessagesProj/src/main/res/raw/ic_unpin.json create mode 100644 TMessagesProj/src/main/res/raw/permission_map.svg create mode 100644 TMessagesProj/src/main/res/raw/permission_map_dark.svg create mode 100644 TMessagesProj/src/main/res/raw/permission_pin.svg create mode 100644 TMessagesProj/src/main/res/raw/permission_pin_dark.svg create mode 100644 TMessagesProj/src/main/res/raw/player_prev.json diff --git a/Dockerfile b/Dockerfile index 17b5ea46e..b9886fbd8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM gradle:6.1.1-jdk8 +FROM gradle:6.5.0-jdk8 ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip ENV ANDROID_API_LEVEL android-30 diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 56a6b3811..a61a1f914 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -17,7 +17,7 @@ configurations.all { dependencies { implementation 'androidx.core:core:1.3.2' implementation 'androidx.palette:palette:1.0.0' - implementation 'androidx.exifinterface:exifinterface:1.3.0' + implementation 'androidx.exifinterface:exifinterface:1.3.1' implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0' implementation 'androidx.multidex:multidex:2.0.1' implementation "androidx.sharetarget:sharetarget:1.0.0" @@ -33,6 +33,7 @@ dependencies { implementation 'com.google.android.gms:play-services-vision:16.2.0' implementation 'com.google.android.gms:play-services-wearable:17.0.0' implementation 'com.google.android.gms:play-services-location:17.1.0' + implementation 'com.google.android.gms:play-services-wallet:18.1.2' implementation "com.microsoft.appcenter:appcenter-distribute:3.3.1" implementation "com.microsoft.appcenter:appcenter-crashes:3.3.1" implementation 'com.googlecode.mp4parser:isoparser:1.0.6' @@ -284,28 +285,12 @@ android { } } - defaultConfig.versionCode = 2103 + defaultConfig.versionCode = 2128 applicationVariants.all { variant -> variant.outputs.all { output -> outputFileName = "app.apk" - output.getProcessManifestProvider().get().doLast { - def abiVersion = variant.productFlavors.get(0).abiVersionCode - - def outputDir = manifestOutputDirectory - File directory - if (outputDir instanceof File) { - directory = outputDir - } else { - directory = outputDir.get().asFile - } - - String manifestPath = directory.toString() + "/AndroidManifest.xml" - def manifestContent = file(manifestPath).getText() - - manifestContent = manifestContent.replace(String.format('android:versionCode="%d"', defaultConfig.versionCode), String.format('android:versionCode="%s"', defaultConfig.versionCode * 10 + abiVersion)) - file(manifestPath).write(manifestContent) - } + output.versionCodeOverride = defaultConfig.versionCode * 10 + variant.productFlavors.get(0).abiVersionCode } } @@ -319,7 +304,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 28 - versionName "7.1.3" + versionName "7.2.0" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/jni/CMakeLists.txt b/TMessagesProj/jni/CMakeLists.txt index 238da90ee..b22a566f5 100644 --- a/TMessagesProj/jni/CMakeLists.txt +++ b/TMessagesProj/jni/CMakeLists.txt @@ -395,7 +395,7 @@ target_compile_definitions(sqlite PUBLIC #voip include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt) -set(NATIVE_LIB "tmessages.33") +set(NATIVE_LIB "tmessages.34") #tmessages add_library(${NATIVE_LIB} SHARED diff --git a/TMessagesProj/jni/TgNetWrapper.cpp b/TMessagesProj/jni/TgNetWrapper.cpp index e65a2f4ce..e8cba5f18 100644 --- a/TMessagesProj/jni/TgNetWrapper.cpp +++ b/TMessagesProj/jni/TgNetWrapper.cpp @@ -80,6 +80,10 @@ jint getCurrentTime(JNIEnv *env, jclass c, jint instanceNum) { return ConnectionsManager::getInstance(instanceNum).getCurrentTime(); } +jint getCurrentDatacenterId(JNIEnv *env, jclass c, jint instanceNum) { + return ConnectionsManager::getInstance(instanceNum).getCurrentDatacenterId(); +} + jint isTestBackend(JNIEnv *env, jclass c, jint instanceNum) { return ConnectionsManager::getInstance(instanceNum).isTestBackend() ? 1 : 0; } @@ -424,6 +428,7 @@ static const char *ConnectionsManagerClassPathName = "org/telegram/tgnet/Connect static JNINativeMethod ConnectionsManagerMethods[] = { {"native_getCurrentTimeMillis", "(I)J", (void *) getCurrentTimeMillis}, {"native_getCurrentTime", "(I)I", (void *) getCurrentTime}, + {"native_getCurrentDatacenterId", "(I)I", (void *) getCurrentDatacenterId}, {"native_isTestBackend", "(I)I", (void *) isTestBackend}, {"native_getTimeDifference", "(I)I", (void *) getTimeDifference}, {"native_sendRequest", "(IJLorg/telegram/tgnet/RequestDelegateInternal;Lorg/telegram/tgnet/QuickAckDelegate;Lorg/telegram/tgnet/WriteToSocketDelegate;IIIZI)V", (void *) sendRequest}, diff --git a/TMessagesProj/jni/lottie.cpp b/TMessagesProj/jni/lottie.cpp index cefb2d89a..429b22d37 100644 --- a/TMessagesProj/jni/lottie.cpp +++ b/TMessagesProj/jni/lottie.cpp @@ -299,7 +299,7 @@ JNIEXPORT void Java_org_telegram_ui_Components_RLottieDrawable_createCache(JNIEn for (size_t a = 0; a < info->frameCount; a += framesPerUpdate) { Surface &surfaceToRender = num % 2 == 0 ? surface1 : surface2; num++; - info->animation->renderSync(a, surfaceToRender); + info->animation->renderSync(a, surfaceToRender, true); if (a != 0) { std::unique_lock lk(cacheDoneMutex); cacheDoneCv.wait(lk, [] { return !frameReady.load(); }); @@ -317,6 +317,7 @@ JNIEXPORT void Java_org_telegram_ui_Components_RLottieDrawable_createCache(JNIEn //DEBUG_D("sticker time = %d", (int) (ConnectionsManager::getInstance(0).getCurrentTimeMonotonicMillis() - time)); delete[] info->compressBuffer; + delete[] firstBuffer; delete[] secondBuffer; fseek(info->precacheFile, 0, SEEK_SET); uint8_t byte = 1; @@ -332,7 +333,7 @@ JNIEXPORT void Java_org_telegram_ui_Components_RLottieDrawable_createCache(JNIEn } } -JNIEXPORT jint Java_org_telegram_ui_Components_RLottieDrawable_getFrame(JNIEnv *env, jclass clazz, jlong ptr, jint frame, jobject bitmap, jint w, jint h, jint stride) { +JNIEXPORT jint Java_org_telegram_ui_Components_RLottieDrawable_getFrame(JNIEnv *env, jclass clazz, jlong ptr, jint frame, jobject bitmap, jint w, jint h, jint stride, jboolean clear) { if (!ptr || bitmap == nullptr) { return 0; } @@ -384,7 +385,7 @@ JNIEXPORT jint Java_org_telegram_ui_Components_RLottieDrawable_getFrame(JNIEnv * if (!loadedFromCache) { if (!info->nextFrameIsCacheFrame || !info->precache) { Surface surface((uint32_t *) pixels, (size_t) w, (size_t) h, (size_t) stride); - info->animation->renderSync((size_t) frame, surface); + info->animation->renderSync((size_t) frame, surface, clear); info->nextFrameIsCacheFrame = true; } } diff --git a/TMessagesProj/jni/rlottie/inc/rlottie.h b/TMessagesProj/jni/rlottie/inc/rlottie.h index ea0d0da60..296546a9c 100755 --- a/TMessagesProj/jni/rlottie/inc/rlottie.h +++ b/TMessagesProj/jni/rlottie/inc/rlottie.h @@ -345,7 +345,7 @@ public: * * @internal */ - void renderSync(size_t frameNo, Surface &surface); + void renderSync(size_t frameNo, Surface &surface, bool clear); /** * @brief Returns root layer of the composition updated with diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieanimation.cpp b/TMessagesProj/jni/rlottie/src/lottie/lottieanimation.cpp index 429d6c7f7..743002b83 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieanimation.cpp +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieanimation.cpp @@ -44,7 +44,7 @@ public: double frameRate() const { return mModel->frameRate(); } size_t totalFrame() const { return mModel->totalFrame(); } size_t frameAtPos(double pos) const { return mModel->frameAtPos(pos); } - Surface render(size_t frameNo, const Surface &surface); + Surface render(size_t frameNo, const Surface &surface, bool clear); const LOTLayerNode * renderTree(size_t frameNo, const VSize &size); const LayerInfoList &layerInfoList() const @@ -93,7 +93,7 @@ bool AnimationImpl::update(size_t frameNo, const VSize &size) return mCompItem->update(frameNo); } -Surface AnimationImpl::render(size_t frameNo, const Surface &surface) +Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool clear) { bool renderInProgress = mRenderInProgress.load(); if (renderInProgress) { @@ -104,7 +104,7 @@ Surface AnimationImpl::render(size_t frameNo, const Surface &surface) mRenderInProgress.store(true); update(frameNo, VSize(surface.drawRegionWidth(), surface.drawRegionHeight())); - mCompItem->render(surface); + mCompItem->render(surface, clear); mRenderInProgress.store(false); return surface; @@ -201,9 +201,9 @@ const LOTLayerNode *Animation::renderTree(size_t frameNo, size_t width, return d->renderTree(frameNo, VSize(width, height)); } -void Animation::renderSync(size_t frameNo, Surface &surface) +void Animation::renderSync(size_t frameNo, Surface &surface, bool clear) { - d->render(frameNo, surface); + d->render(frameNo, surface, clear); } const LayerInfoList &Animation::layers() const diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp index 1e86d368a..3221c246d 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp @@ -175,7 +175,7 @@ const LOTLayerNode *LOTCompItem::renderTree() const return mRootLayer->layerNode(); } -bool LOTCompItem::render(const rlottie::Surface &surface) +bool LOTCompItem::render(const rlottie::Surface &surface, bool clear) { VBitmap bitmap(reinterpret_cast(surface.buffer()), surface.width(), surface.height(), surface.bytesPerLine(), @@ -190,7 +190,7 @@ bool LOTCompItem::render(const rlottie::Surface &surface) e->preprocess(clip); } - VPainter painter(&bitmap); + VPainter painter(&bitmap, clear); // set sub surface area for drawing. painter.setDrawRegion( VRect(surface.drawRegionPosX(), surface.drawRegionPosY(), @@ -609,7 +609,7 @@ void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask, VPainter srcPainter; VBitmap srcBitmap(size.width(), size.height(), VBitmap::Format::ARGB32); - srcPainter.begin(&srcBitmap); + srcPainter.begin(&srcBitmap, true); renderHelper(&srcPainter, inheritMask, matteRle); srcPainter.end(); painter->drawBitmap(VPoint(), srcBitmap, combinedAlpha() * 255); @@ -669,7 +669,7 @@ void LOTCompLayerItem::renderMatteLayer(VPainter *painter, const VRle &mask, VPainter srcPainter; src->bitmap().reset(size.width(), size.height(), VBitmap::Format::ARGB32); - srcPainter.begin(&src->bitmap()); + srcPainter.begin(&src->bitmap(), true); src->render(&srcPainter, mask, matteRle); srcPainter.end(); @@ -677,7 +677,7 @@ void LOTCompLayerItem::renderMatteLayer(VPainter *painter, const VRle &mask, VPainter layerPainter; layer->bitmap().reset(size.width(), size.height(), VBitmap::Format::ARGB32); - layerPainter.begin(&layer->bitmap()); + layerPainter.begin(&layer->bitmap(), true); layer->render(&layerPainter, mask, matteRle); // 2.1update composition mode diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h index 80517ac51..2450b4a23 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h @@ -70,7 +70,7 @@ public: VSize size() const; void buildRenderTree(); const LOTLayerNode * renderTree()const; - bool render(const rlottie::Surface &surface); + bool render(const rlottie::Surface &surface, bool clear); void setValue(const std::string &keypath, LOTVariant &value); void resetCurrentFrame(); private: diff --git a/TMessagesProj/jni/rlottie/src/vector/vpainter.cpp b/TMessagesProj/jni/rlottie/src/vector/vpainter.cpp index cdcaa11f4..365adcdb3 100755 --- a/TMessagesProj/jni/rlottie/src/vector/vpainter.cpp +++ b/TMessagesProj/jni/rlottie/src/vector/vpainter.cpp @@ -115,17 +115,19 @@ VPainter::VPainter() mImpl = new VPainterImpl; } -VPainter::VPainter(VBitmap *buffer) +VPainter::VPainter(VBitmap *buffer, bool clear) { mImpl = new VPainterImpl; - begin(buffer); + begin(buffer, clear); } -bool VPainter::begin(VBitmap *buffer) +bool VPainter::begin(VBitmap *buffer, bool clear) { mImpl->mBuffer.prepare(buffer); mImpl->mSpanData.init(&mImpl->mBuffer); // TODO find a better api to clear the surface - mImpl->mBuffer.clear(); + if (clear) { + mImpl->mBuffer.clear(); + } return true; } void VPainter::end() {} diff --git a/TMessagesProj/jni/rlottie/src/vector/vpainter.h b/TMessagesProj/jni/rlottie/src/vector/vpainter.h index 2d523370d..2aaf99925 100755 --- a/TMessagesProj/jni/rlottie/src/vector/vpainter.h +++ b/TMessagesProj/jni/rlottie/src/vector/vpainter.h @@ -37,8 +37,8 @@ public: }; ~VPainter(); VPainter(); - VPainter(VBitmap *buffer); - bool begin(VBitmap *buffer); + VPainter(VBitmap *buffer, bool clear); + bool begin(VBitmap *buffer, bool clear); void end(); void setDrawRegion(const VRect ®ion); // sub surface rendering area. void setBrush(const VBrush &brush); diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 23c3ce3bc..209ce5814 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -564,6 +564,11 @@ int32_t ConnectionsManager::getCurrentTime() { return (int32_t) (getCurrentTimeMillis() / 1000) + timeDifference; } +uint32_t ConnectionsManager::getCurrentDatacenterId() { + Datacenter *datacenter = getDatacenterWithId(DEFAULT_DATACENTER_ID); + return datacenter != nullptr ? datacenter->getDatacenterId() : INT_MAX; +} + bool ConnectionsManager::isTestBackend() { return testBackend; } @@ -2796,7 +2801,7 @@ std::unique_ptr ConnectionsManager::wrapInLayer(TLObject *object, Data invokeWithLayer *request2 = new invokeWithLayer(); request2->layer = currentLayer; request2->query = std::unique_ptr(request); - if (LOGS_ENABLED) DEBUG_D("wrap in layer %s", typeid(*object).name()); + if (LOGS_ENABLED) DEBUG_D("wrap in layer %s, flags = %d", typeid(*object).name(), request->flags); return std::unique_ptr(request2); } } diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.h b/TMessagesProj/jni/tgnet/ConnectionsManager.h index 2f6f96e84..2f16321ba 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.h +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.h @@ -45,6 +45,7 @@ public: int64_t getCurrentTimeMillis(); int64_t getCurrentTimeMonotonicMillis(); int32_t getCurrentTime(); + uint32_t getCurrentDatacenterId(); bool isTestBackend(); int32_t getTimeDifference(); int32_t sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate); diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 64172bbfb..bb9aace5c 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -394,7 +394,7 @@ - + diff --git a/TMessagesProj/src/main/assets/arctic.attheme b/TMessagesProj/src/main/assets/arctic.attheme index 4bf59b35c..5465ce92e 100644 --- a/TMessagesProj/src/main/assets/arctic.attheme +++ b/TMessagesProj/src/main/assets/arctic.attheme @@ -92,7 +92,7 @@ dialogProgressCircle=-12281108 avatar_subtitleInProfilePink=-16777216 player_progress=-14441474 chat_inReplyLine=-12478487 -dialogLineProgressBackground=-3875601 +dialogLineProgressBackground=-3152133 chat_inReplyNameText=-13464859 chat_outAudioPerfomerSelectedText=-1 profile_title=-13224394 @@ -122,6 +122,7 @@ dialogTextBlue2=-14772773 dialogTextBlue3=-14839830 dialogTextBlue4=-15625752 actionBarTabActiveText=-13590803 +chat_topPanelMessage=-8354167 statisticChartLine_golden=-1853657 calls_callReceivedGreenIcon=-13645978 chats_pinnedOverlay=100663296 @@ -279,6 +280,7 @@ windowBackgroundWhiteBlueText4=-12675352 chat_replyPanelMessage=-13355980 chat_inViewsSelected=-6373686 windowBackgroundWhiteLinkSelection=560114147 +inappPlayerClose=-7563878 chat_outMediaIcon=-13332255 chat_outAudioCacheSeekbar=738197503 chats_sentClock=2066650878 diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index 31b59f153..483306f73 100644 --- a/TMessagesProj/src/main/assets/bluebubbles.attheme +++ b/TMessagesProj/src/main/assets/bluebubbles.attheme @@ -48,7 +48,7 @@ chat_inLoaderSelected=-12277262 chat_outLocationIcon=-2105761599 chat_outAudioProgress=-6239505 chat_inReplyLine=-348807706 -dialogLineProgressBackground=-2825240 +dialogLineProgressBackground=-2035723 chat_inReplyNameText=-14643754 statisticChartLine_lightgreen=-7352519 chats_onlineCircle=-13192972 diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index ccb8efbcb..0a3bf5b13 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -3,14 +3,17 @@ chat_inFileBackgroundSelected=-12757128 windowBackgroundChecked=-11632213 radioBackgroundChecked=-10177041 dialogTextBlue=-10177041 +dialog_inlineProgressBackground=-15393241 chat_inSentClockSelected=-7490861 windowBackgroundWhiteBlueIcon=-528890628 avatar_backgroundActionBarGreen=-14602949 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14273984 actionBarActionModeDefaultTop=-14536643 +statisticChartHintLine=452984831 chats_menuPhone=-1816080163 chat_outViews=-7357217 +statisticChartLine_red=-832444 chat_secretTimerBackground=-1239540194 avatar_actionBarSelectorCyan=-12758164 chat_outViaBotNameText=-7551233 @@ -42,8 +45,10 @@ chat_outTimeSelectedText=-4268038 chat_inFileProgressSelected=-1 changephoneinfo_image=-12693922 chat_inAudioPerfomerText=-8812393 +statisticChartBackZoomColor=-12145938 player_button=-1 key_sheet_other=1140850687 +statisticChartLine_lightblue=-12814100 chat_inContactNameText=-8796932 chats_menuPhoneCats=-8613724 chat_outPreviewLine=-6631937 @@ -59,11 +64,12 @@ chat_inFileProgress=-1 dialogIcon=-7627862 chat_emojiPanelEmptyText=-8549479 chat_emojiPanelBackspace=-9996665 -chat_replyPanelClose=-10062202 +chat_replyPanelClose=-9798770 chat_inContactPhoneSelectedText=-7490861 dialogSearchText=-1 actionBarTabUnactiveText=-7628894 chat_outAudioTitleText=-1 +statisticChartActivePickerChart=-665688455 chat_emojiPanelBackground=-14866637 chats_unreadCounter=-10177041 groupcreate_hintText=-8549479 @@ -89,7 +95,7 @@ dialogShadowLine=335544320 groupcreate_onlineText=-10177041 profile_status=-9192457 divider=-1795162112 -chat_topPanelLine=-11108183 +chat_topPanelLine=-10576428 chat_inReplyMessageText=-1 dialogInputField=-8549479 windowBackgroundWhiteInputFieldActivated=-9522449 @@ -109,6 +115,7 @@ chat_inContactPhoneText=-8812393 chat_inlineResultIcon=-8796932 chat_outBubbleGradientSelectedOverlay=352321535 chats_draft=-637778102 +dialogLineProgress=-10576428 listSelector=771751936 chat_outPreviewInstantText=-6631937 chat_inMenuSelected=-1517440301 @@ -127,13 +134,14 @@ player_progress=-10177041 chat_inReplyLine=-8796932 chat_inAudioPerfomerSelectedText=-7490861 dialogBackground=-14602949 -dialogLineProgressBackground=-6242341 +dialogLineProgressBackground=-13548718 chat_inReplyNameText=-8796932 chat_outAudioPerfomerSelectedText=-4268038 actionBarActionModeDefaultIcon=-1 windowBackgroundWhiteRedText4=-3187617 chat_goDownButtonIcon=-1 windowBackgroundWhiteRedText5=-1152913 +statisticChartLine_lightgreen=-7352519 chat_outAudioSelectedProgress=-1 chat_messageTextOut=-328966 chat_inInstant=-8796932 @@ -172,12 +180,15 @@ chat_attachUnactiveTab=-9596506 windowBackgroundWhiteGreenText=-10371737 actionBarTabActiveText=-9781249 chat_emojiPanelIcon=-9996665 -chat_topPanelMessage=-7628894 +chat_topPanelMessage=-8220258 +statisticChartLine_golden=-2184161 +statisticChartSignatureAlpha=-1946157057 chat_emojiPanelTrendingDescription=-8549479 calls_callReceivedGreenIcon=-12001930 chats_pinnedOverlay=16777215 windowBackgroundWhiteInputField=-12035217 avatar_backgroundRed=-2326437 +statisticChartLine_green=-12729793 chat_emojiPanelIconSelector=-10177041 chat_emojiPanelBadgeBackground=-11291403 chat_inForwardedNameText=-8796932 @@ -189,6 +200,7 @@ chat_linkSelectBackground=1516415459 windowBackgroundWhiteBlueText=-10177041 avatar_nameInMessageCyan=-10623523 chat_inLocationBackground=-13417903 +statisticChartHighlightColor=-2030043137 radioBackground=-1635939431 profile_tabText=-8549479 contextProgressOuter1=-9914632 @@ -236,7 +248,8 @@ chat_attachCameraIcon1=-32171 undo_background=-182112197 avatar_actionBarSelectorPink=-12758164 dialogTextHint=-8549479 -chat_topPanelTitle=-11164709 +statisticChartLine_orange=-1720817 +chat_topPanelTitle=-9719066 chat_inAudioCacheSeekbar=-11443856 chat_outContactIcon=-1 chat_inFileInfoText=-8812137 @@ -246,12 +259,13 @@ profile_creatorIcon=-10177041 profile_actionBackground=-10376479 avatar_subtitleInProfileGreen=-7628894 chats_sentCheck=-10177041 +statisticChartInactivePickerChart=-936297140 chats_unreadCounterMuted=-12692893 chat_outVoiceSeekbarFill=-7944965 chat_outReplyLine=-6631937 chat_messagePanelIcons=-9733492 chat_inReplyMediaMessageText=-8812393 -inappPlayerTitle=-8549479 +inappPlayerTitle=-8220258 chat_emojiPanelIconSelected=-10177041 progressCircle=-10177027 chat_inContactBackground=-10445358 @@ -266,7 +280,7 @@ chat_mediaSentClock=-1291845633 files_folderIcon=-1 chats_menuCloudBackgroundCats=-11232035 switchTrackBlue=-10984850 -chat_topPanelClose=-10590606 +chat_topPanelClose=-9074276 profile_adminIcon=-8549479 chats_verifiedBackground=-10177041 chat_inTimeSelectedText=-7490861 @@ -282,6 +296,7 @@ picker_enabledButton=-9781249 inappPlayerBackground=-14602949 avatar_nameInMessagePink=-624741 windowBackgroundWhiteGrayText=-8549479 +statisticChartSignature=-1214008894 avatar_actionBarSelectorViolet=-12758164 chat_attachPollBackground=-2183099 avatar_nameInMessageBlue=-8796932 @@ -311,6 +326,7 @@ dialogBadgeBackground=-10177041 chat_outBubbleSelected=-11829841 avatar_backgroundInProfileBlue=-11232035 chat_inFileNameText=-1 +statisticChartLine_blue=-11362305 inappPlayerPerformer=-1 chat_inInstantSelected=-5648402 chat_outFileInfoText=-7357217 @@ -319,6 +335,7 @@ groupcreate_checkboxCheck=-1 chat_outContactPhoneSelectedText=-4268038 chat_unreadMessagesStartBackground=-14339006 chat_inLoaderPhoto=-14404542 +statisticChartCheckboxInactive=-6579301 chat_inFileInfoSelectedText=-7490861 chat_wallpaper=-15393241 chat_outMenuSelected=-541138950 @@ -347,6 +364,7 @@ chat_outBubble=-12689014 avatar_backgroundActionBarCyan=-14602949 chat_attachFileBackground=-10830604 chat_attachHideBackground=-14074026 +statisticChartChevronColor=-9012091 chats_menuItemText=-184549377 chats_message=-8549479 chat_outReplyNameText=-6631937 @@ -369,11 +387,11 @@ windowBackgroundWhiteBlueText3=-10177041 windowBackgroundWhiteBlueText2=-8796932 windowBackgroundWhiteBlueText5=-10177041 windowBackgroundWhiteBlueText4=-10177041 -chat_replyPanelMessage=-8812137 +chat_replyPanelMessage=-7628894 chat_inViewsSelected=-7490861 windowBackgroundWhiteLinkSelection=862238205 player_background=-14734794 -inappPlayerClose=-8549479 +inappPlayerClose=-9336677 chat_outMediaIcon=-1 chats_message_threeLines=-8549479 player_actionBarSubtitle=-8549479 @@ -383,6 +401,7 @@ chats_sentClock=-11772054 chat_inAudioSeekbar=-11443856 avatar_subtitleInProfileRed=-7628894 avatar_backgroundActionBarRed=-14602949 +statisticChartLine_indigo=-7906078 dialogSearchIcon=-8945521 chat_inPreviewInstantText=-8796932 chats_archiveBackground=-11036980 @@ -407,6 +426,7 @@ windowBackgroundWhiteGrayText3=-8549479 windowBackgroundWhiteGrayText4=-931296359 chat_inTimeText=-645885536 dialogRadioBackground=-11245959 +statisticChartRipple=748994002 chat_outReplyMessageText=-1 chat_recordedVoiceDot=-1221292 chat_messagePanelBackground=-14602949 @@ -426,6 +446,7 @@ windowBackgroundWhiteValueText=-528890628 chat_outAudioDurationText=-7357217 chat_outMenu=-9594162 chat_goDownButton=-14602949 +statisticChartActiveLine=855638015 chats_secretName=-9316522 chat_inMenu=2039722445 chat_recordVoiceCancel=-8549479 @@ -441,22 +462,3 @@ chat_outSentClock=-8213557 dialogBackgroundGray=-14932431 chat_searchPanelText=-8796932 chat_inContactIcon=-1 -statisticChartSignatureAlpha=-1946157057 -statisticChartRipple=748994002 -statisticChartCheckboxInactive=-6579301 -statisticChartBackZoomColor=-12145938 -statisticChartChevronColor=-9012091 -statisticChartHighlightColor=-2030043137 -statisticChartHintLine=452984831 -statisticChartLine_red=-832444 -statisticChartLine_lightblue=-12814100 -statisticChartActivePickerChart=-665688455 -statisticChartLine_lightgreen=-7352519 -statisticChartLine_golden=-2184161 -statisticChartLine_green=-12729793 -statisticChartLine_orange=-1720817 -statisticChartInactivePickerChart=-936297140 -statisticChartSignature=-1214008894 -statisticChartLine_blue=-11362305 -statisticChartLine_indigo=-7906078 -statisticChartActiveLine=855638015 diff --git a/TMessagesProj/src/main/assets/day.attheme b/TMessagesProj/src/main/assets/day.attheme index f2e4a7d6a..43822a88d 100644 --- a/TMessagesProj/src/main/assets/day.attheme +++ b/TMessagesProj/src/main/assets/day.attheme @@ -98,7 +98,7 @@ avatar_subtitleInProfilePink=-16777216 player_progress=-14574092 chat_stickerReplyMessageText=-7565679 chat_inReplyLine=-12676640 -dialogLineProgressBackground=-3875601 +dialogLineProgressBackground=-3348999 chat_inReplyNameText=-13531425 chat_outAudioPerfomerSelectedText=-1 profile_title=-13224394 @@ -129,6 +129,7 @@ dialogTextBlue2=-14772773 dialogTextBlue3=-14839830 dialogTextBlue4=-15625752 actionBarTabActiveText=-15755027 +chat_topPanelMessage=-8419703 chat_stickerNameText=-1 statisticChartLine_golden=-1853657 calls_callReceivedGreenIcon=-13645978 @@ -204,6 +205,7 @@ chats_sentCheck=-15032337 chat_outVoiceSeekbarFill=-1 chat_outReplyLine=-1 chat_inAudioSeekbarFill=-11426840 +inappPlayerTitle=-14276824 progressCircle=-12605954 chat_inContactBackground=-13393417 chat_outVenueInfoSelectedText=-3676417 @@ -301,6 +303,7 @@ windowBackgroundWhiteBlueText4=-12675352 chat_replyPanelMessage=-13355980 chat_inViewsSelected=-258105181 windowBackgroundWhiteLinkSelection=560114147 +inappPlayerClose=-7563878 chat_outMediaIcon=-14707997 chat_outAudioCacheSeekbar=738197503 chats_sentClock=2073474246 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 2587a007b..59fbe938a 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -9,8 +9,10 @@ avatar_backgroundActionBarGreen=-14602949 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14211289 actionBarActionModeDefaultTop=-14277082 +statisticChartHintLine=452984831 chats_menuPhone=-1815557944 chat_outViews=-7357217 +statisticChartLine_red=-832444 chat_secretTimerBackground=-1239540194 avatar_actionBarSelectorCyan=-12758164 chat_outViaBotNameText=-5448193 @@ -43,8 +45,10 @@ chat_outTimeSelectedText=-7023626 chat_inFileProgressSelected=-1 changephoneinfo_image=-11184811 chat_inAudioPerfomerText=-8618883 +statisticChartBackZoomColor=-12145938 player_button=-1 key_sheet_other=1140850687 +statisticChartLine_lightblue=-12814100 chat_inContactNameText=-8796932 chats_menuPhoneCats=-8224126 chat_outPreviewLine=-6631937 @@ -62,11 +66,12 @@ chat_inFileProgress=-1 dialogIcon=-7566196 chat_emojiPanelEmptyText=-8553090 chat_emojiPanelBackspace=-9539985 -chat_replyPanelClose=-9539985 +chat_replyPanelClose=-9013383 chat_inContactPhoneSelectedText=-7490861 dialogSearchText=-1 actionBarTabUnactiveText=-7434609 chat_outAudioTitleText=-1 +statisticChartActivePickerChart=-665229191 chat_emojiPanelBackground=-14803425 chats_unreadCounter=-13000973 groupcreate_hintText=-8553091 @@ -134,13 +139,14 @@ player_progress=-11292689 chat_inReplyLine=-8796932 chat_inAudioPerfomerSelectedText=-7490861 dialogBackground=-14803426 -dialogLineProgressBackground=-10132123 +dialogLineProgressBackground=-12303292 chat_inReplyNameText=-8796932 chat_outAudioPerfomerSelectedText=-7023626 actionBarActionModeDefaultIcon=-1 windowBackgroundWhiteRedText4=-3187617 chat_goDownButtonIcon=-1 windowBackgroundWhiteRedText5=-1152913 +statisticChartLine_lightgreen=-7352519 chats_onlineCircle=-13130503 chat_outAudioSelectedProgress=-1 chat_messageTextOut=-328966 @@ -168,7 +174,7 @@ chats_nameMessageArchived=-8553091 avatar_nameInMessageOrange=-13984 chats_pinnedIcon=-10197916 chat_attachActiveTab=-9781249 -chat_replyPanelLine=1779898909 +chat_replyPanelLine=-1509949440 avatar_subtitleInProfileOrange=-7628894 chat_outSentCheckSelected=-5841921 dialogSearchHint=-8421505 @@ -183,13 +189,16 @@ chat_attachUnactiveTab=-9596506 windowBackgroundWhiteGreenText=-10371737 actionBarTabActiveText=-10698241 chat_emojiPanelIcon=-9539985 -chat_topPanelMessage=-7895160 +chat_topPanelMessage=-8618626 +statisticChartLine_golden=-2184161 +statisticChartSignatureAlpha=-1946157057 chat_emojiSearchIcon=-9211020 chat_emojiPanelTrendingDescription=-8553090 calls_callReceivedGreenIcon=-12001930 chats_pinnedOverlay=16777215 windowBackgroundWhiteInputField=-11513776 avatar_backgroundRed=-2326437 +statisticChartLine_green=-12729793 chat_emojiPanelIconSelector=-10177041 chat_emojiPanelBadgeBackground=-11291403 chat_inForwardedNameText=-8930052 @@ -203,6 +212,7 @@ chats_archivePullDownBackground=-14145496 windowBackgroundWhiteBlueText=-10177041 avatar_nameInMessageCyan=-10623523 chat_inLocationBackground=-12829636 +statisticChartHighlightColor=-2030043137 radioBackground=-1635939431 contextProgressOuter1=-11555592 chat_inFileIcon=-14145496 @@ -253,6 +263,7 @@ chat_attachCameraIcon1=-32171 undo_background=-181917656 avatar_actionBarSelectorPink=-12758164 dialogTextHint=-8553091 +statisticChartLine_orange=-1457126 chat_topPanelTitle=-10638868 chat_inAudioCacheSeekbar=-10461088 chat_outContactIcon=-1 @@ -264,12 +275,13 @@ profile_creatorIcon=-10177041 profile_actionBackground=-11560229 avatar_subtitleInProfileGreen=-7628894 chats_sentCheck=-12145165 +statisticChartInactivePickerChart=-667862461 chats_unreadCounterMuted=-12237499 chat_outVoiceSeekbarFill=-1 chat_outReplyLine=-8466689 chat_messagePanelIcons=-8947847 chat_inReplyMediaMessageText=-8355711 -inappPlayerTitle=-8553090 +inappPlayerTitle=-8618626 chat_emojiPanelIconSelected=-10177041 progressCircle=-10177027 chat_inContactBackground=-11494936 @@ -285,7 +297,7 @@ files_folderIcon=-1 chat_outTextSelectionHighlight=2122236141 chats_menuCloudBackgroundCats=-11232035 switchTrackBlue=-9934742 -chat_topPanelClose=-10461087 +chat_topPanelClose=-9013383 profile_adminIcon=-8549479 chats_verifiedBackground=-12145929 chat_inTimeSelectedText=-7490861 @@ -301,6 +313,7 @@ picker_enabledButton=-9781249 inappPlayerBackground=-15066597 avatar_nameInMessagePink=-624741 windowBackgroundWhiteGrayText=-8553091 +statisticChartSignature=-1214008894 actionBarDefaultSubmenuItemIcon=-8421504 avatar_actionBarSelectorViolet=-12758164 chat_attachPollBackground=-2183099 @@ -331,6 +344,7 @@ dialogBadgeBackground=-10177041 chat_outBubbleSelected=-11829841 avatar_backgroundInProfileBlue=-11232035 chat_inFileNameText=-1 +statisticChartLine_blue=-11362305 inappPlayerPerformer=-1 chat_inInstantSelected=-5648402 chat_outFileInfoText=-7357217 @@ -339,6 +353,7 @@ groupcreate_checkboxCheck=-1 chat_outContactPhoneSelectedText=-7023626 chat_unreadMessagesStartBackground=-14606046 chat_inLoaderPhoto=-13882324 +statisticChartCheckboxInactive=-6579301 chat_inFileInfoSelectedText=-7490861 chat_wallpaper=-16316665 chat_outMenuSelected=-541138950 @@ -369,6 +384,7 @@ chat_outBubble=-13210449 avatar_backgroundActionBarCyan=-14602949 chat_attachFileBackground=-10830604 chat_attachHideBackground=-14074026 +statisticChartChevronColor=-9012091 chats_menuItemText=-184549377 chats_message=-8224126 chat_outReplyNameText=-6301185 @@ -398,7 +414,7 @@ chat_inViewsSelected=-7490861 chat_emojiBottomPanelIcon=-9539985 windowBackgroundWhiteLinkSelection=1030010365 player_background=-14474461 -inappPlayerClose=-8553090 +inappPlayerClose=-9013383 chat_outMediaIcon=-1 chats_message_threeLines=-8224126 player_actionBarSubtitle=-8553091 @@ -408,6 +424,7 @@ chats_sentClock=-9539986 chat_inAudioSeekbar=-11119018 avatar_subtitleInProfileRed=-7628894 avatar_backgroundActionBarRed=-14602949 +statisticChartLine_indigo=-7906075 dialogSearchIcon=-8882056 chat_inPreviewInstantText=-8796932 chats_archiveBackground=-12219694 @@ -432,6 +449,7 @@ windowBackgroundWhiteGrayText3=-8553091 windowBackgroundWhiteGrayText4=-10987432 chat_inTimeText=-8355711 dialogRadioBackground=-10855846 +statisticChartRipple=748994002 chat_outBubbleGradient=-12874567 chat_outReplyMessageText=-1 chat_recordedVoiceDot=-1221292 @@ -470,22 +488,3 @@ chat_outSentClock=-8213557 dialogBackgroundGray=-14013910 chat_searchPanelText=-10767620 chat_inContactIcon=-1 -statisticChartSignatureAlpha=-1946157057 -statisticChartRipple=748994002 -statisticChartCheckboxInactive=-6579301 -statisticChartBackZoomColor=-12145938 -statisticChartChevronColor=-9012091 -statisticChartHighlightColor=-2030043137 -statisticChartHintLine=452984831 -statisticChartLine_red=-832444 -statisticChartLine_lightblue=-12814100 -statisticChartActivePickerChart=-665229191 -statisticChartLine_lightgreen=-7352519 -statisticChartLine_golden=-2184161 -statisticChartLine_green=-12729793 -statisticChartLine_orange=-1457126 -statisticChartInactivePickerChart=-667862461 -statisticChartSignature=-1214008894 -statisticChartLine_blue=-11362305 -statisticChartLine_indigo=-7906075 -statisticChartActiveLine=855638015 \ No newline at end of file diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java index 8ead430d6..a13365135 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java @@ -6,8 +6,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.os.Build; -import android.util.SparseArray; -import android.util.SparseLongArray; import android.view.View; import android.view.ViewPropertyAnimator; import android.view.animation.OvershootInterpolator; @@ -16,8 +14,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; @@ -255,6 +251,10 @@ public class ChatListItemAnimator extends DefaultItemAnimator { if (!shouldAnimateEnterFromBottom) { holder.itemView.setScaleX(0.9f); holder.itemView.setScaleY(0.9f); + } else { + if (holder.itemView instanceof ChatMessageCell) { + ((ChatMessageCell) holder.itemView).getTransitionParams().messageEntering = true; + } } mPendingAdditions.add(holder); return true; @@ -281,16 +281,21 @@ public class ChatListItemAnimator extends DefaultItemAnimator { @Override public void onAnimationCancel(Animator animator) { view.setTranslationY(0); + if (view instanceof ChatMessageCell) { + ((ChatMessageCell) view).getTransitionParams().messageEntering = false; + } } @Override public void onAnimationEnd(Animator animator) { + if (view instanceof ChatMessageCell) { + ((ChatMessageCell) view).getTransitionParams().messageEntering = false; + } animation.setListener(null); if (mAddAnimations.remove(holder)) { dispatchAddFinished(holder); dispatchFinishedWhenDone(); } - } }).start(); } @@ -341,8 +346,13 @@ public class ChatListItemAnimator extends DefaultItemAnimator { FileLog.d("animate move"); } final View view = holder.itemView; + ChatMessageCell chatMessageCell = null; if (holder.itemView instanceof ChatMessageCell) { - fromX += (int) ((ChatMessageCell) holder.itemView).getAnimationOffsetX(); + chatMessageCell = ((ChatMessageCell) holder.itemView); + fromX += (int) chatMessageCell.getAnimationOffsetX(); + if (chatMessageCell.getTransitionParams().lastTopOffset != chatMessageCell.getTopMediaOffset()) { + fromY += chatMessageCell.getTransitionParams().lastTopOffset - chatMessageCell.getTopMediaOffset(); + } } else { fromX += (int) holder.itemView.getTranslationX(); } @@ -356,8 +366,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { MoveInfoExtended moveInfo = new MoveInfoExtended(holder, fromX, fromY, toX, toY); - if (holder.itemView instanceof ChatMessageCell) { - ChatMessageCell chatMessageCell = (ChatMessageCell) holder.itemView; + if (chatMessageCell != null) { ChatMessageCell.TransitionParams params = chatMessageCell.getTransitionParams(); if (!params.supportChangeAnimation()) { @@ -563,6 +572,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { moveInfo.animateChangeInternal = chatMessageCell.getTransitionParams().animateChange(); if (moveInfo.animateChangeInternal) { + chatMessageCell.getTransitionParams().animateChange = true; chatMessageCell.getTransitionParams().animateChangeProgress = 0f; } @@ -610,7 +620,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { if (holder.itemView instanceof BotHelpCell) { BotHelpCell botCell = (BotHelpCell) holder.itemView ; - int top = recyclerListView.getMeasuredHeight() / 2 - botCell.getMeasuredHeight() / 2 + recyclerListView.getPaddingTop(); + int top = recyclerListView.getMeasuredHeight() / 2 - botCell.getMeasuredHeight() / 2 + activity.getChatListViewPadding(); float animateTo = 0; if (botCell.getTop() > top) { animateTo = top - botCell.getTop(); @@ -748,6 +758,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { if (moveInfoExtended.animateChangeInternal) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); + params.animateChange = true; valueAnimator.addUpdateListener(animation -> { params.animateChangeProgress = (float) animation.getAnimatedValue(); chatMessageCell.invalidate(); @@ -950,9 +961,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { FileLog.d("all animations done"); } - if (!reset) { - recyclerListView.setClipChildren(true); - } + recyclerListView.setClipChildren(true); while (!runOnAnimationsEnd.isEmpty()) { runOnAnimationsEnd.remove(0).run(); } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java index 710942bcb..99fc2e3f2 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java @@ -295,9 +295,6 @@ public class ChildHelper { final int offset = getOffset(index); mBucket.remove(offset); mCallback.detachViewFromParent(offset); - if (DEBUG) { - Log.d(TAG, "detach view from parent " + index + ", off:" + offset); - } } /** diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java index 88dc4c27e..1a46787e8 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java @@ -966,12 +966,16 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements return fixOffset; } + public int getStarForFixGap() { + return mOrientationHelper.getStartAfterPadding(); + } + /** * @return The final offset amount for children */ private int fixLayoutStartGap(int startOffset, RecyclerView.Recycler recycler, RecyclerView.State state, boolean canOffsetChildren) { - int gap = startOffset - mOrientationHelper.getStartAfterPadding(); + int gap = startOffset - getStarForFixGap(); int fixOffset = 0; if (gap > 0) { // check if we should fix this gap. @@ -1459,21 +1463,33 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements if (mShouldReverseLayout) { for (int i = childCount - 1; i >= 0; i--) { View child = getChildAt(i); - if (mOrientationHelper.getDecoratedEnd(child) > limit - || mOrientationHelper.getTransformedEndWithDecoration(child) > limit) { - // stop here - recycleChildren(recycler, childCount - 1, i); - return; + if (child != null) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); + if (holder == null || holder.shouldIgnore()) { + continue; + } + if (mOrientationHelper.getDecoratedEnd(child) > limit + || mOrientationHelper.getTransformedEndWithDecoration(child) > limit) { + // stop here + recycleChildren(recycler, childCount - 1, i); + return; + } } } } else { for (int i = 0; i < childCount; i++) { View child = getChildAt(i); - if (mOrientationHelper.getDecoratedEnd(child) > limit - || mOrientationHelper.getTransformedEndWithDecoration(child) > limit) { - // stop here - recycleChildren(recycler, 0, i); - return; + if (child != null) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); + if (holder == null || holder.shouldIgnore()) { + continue; + } + if (mOrientationHelper.getDecoratedEnd(child) > limit + || mOrientationHelper.getTransformedEndWithDecoration(child) > limit) { + // stop here + recycleChildren(recycler, 0, i); + return; + } } } } @@ -1507,21 +1523,33 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements if (mShouldReverseLayout) { for (int i = 0; i < childCount; i++) { View child = getChildAt(i); - if (mOrientationHelper.getDecoratedStart(child) < limit - || mOrientationHelper.getTransformedStartWithDecoration(child) < limit) { - // stop here - recycleChildren(recycler, 0, i); - return; + if (child != null) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); + if (holder == null || holder.shouldIgnore()) { + continue; + } + if (mOrientationHelper.getDecoratedStart(child) < limit + || mOrientationHelper.getTransformedStartWithDecoration(child) < limit) { + // stop here + recycleChildren(recycler, 0, i); + return; + } } } } else { for (int i = childCount - 1; i >= 0; i--) { View child = getChildAt(i); - if (mOrientationHelper.getDecoratedStart(child) < limit - || mOrientationHelper.getTransformedStartWithDecoration(child) < limit) { - // stop here - recycleChildren(recycler, childCount - 1, i); - return; + if (child != null) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); + if (holder == null || holder.shouldIgnore()) { + continue; + } + if (mOrientationHelper.getDecoratedStart(child) < limit + || mOrientationHelper.getTransformedStartWithDecoration(child) < limit) { + // stop here + recycleChildren(recycler, childCount - 1, i); + return; + } } } } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java index f94e0dd16..0a981802f 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java @@ -371,7 +371,7 @@ public abstract class OrientationHelper { @Override public int getStartAfterPadding() { - return mLayoutManager.getPaddingTop(); + return mLayoutManager.getStartAfterPadding(); } @Override @@ -418,8 +418,7 @@ public abstract class OrientationHelper { @Override public int getTotalSpace() { - return mLayoutManager.getHeight() - mLayoutManager.getPaddingTop() - - mLayoutManager.getPaddingBottom(); + return mLayoutManager.getTotalSpace(); } @Override diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java index 1f6be08e2..98635a92e 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java @@ -899,13 +899,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, // lazy detach occurs, it will receive invalid attach/detach sequencing. child.clearAnimation(); } - if (VERBOSE_TRACING) { - TraceCompat.beginSection("RV removeViewAt"); - } RecyclerView.this.removeViewAt(index); - if (VERBOSE_TRACING) { - TraceCompat.endSection(); - } } @Override @@ -942,9 +936,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, throw new IllegalArgumentException("Called attach on a child which is not" + " detached: " + vh + exceptionLabel()); } - if (DEBUG) { - Log.d(TAG, "reAttach " + vh); - } vh.clearTmpDetachFlag(); } RecyclerView.this.attachViewToParent(child, index, layoutParams); @@ -960,9 +951,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, throw new IllegalArgumentException("called detach on an already" + " detached child " + vh + exceptionLabel()); } - if (DEBUG) { - Log.d(TAG, "tmpDetach " + vh); - } vh.addFlags(ViewHolder.FLAG_TMP_DETACHED); } } @@ -7558,7 +7546,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, @Override public int getParentStart() { - return LayoutManager.this.getPaddingTop(); + return LayoutManager.this.getParentStart(); } @Override @@ -8835,6 +8823,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, */ public void removeAndRecycleViewAt(int index, @NonNull Recycler recycler) { final View view = getChildAt(index); + ViewHolder holder = getChildViewHolderInt(view); + if (holder.shouldIgnore()) { + return; + } removeViewAt(index); recycler.recycleView(view); } @@ -10591,6 +10583,22 @@ public class RecyclerView extends ViewGroup implements ScrollingView, /** {@link androidx.recyclerview.R.attr#stackFromEnd} */ public boolean stackFromEnd; } + + /** + * Custom methods for ignoring padding + */ + protected int getParentStart() { + return getPaddingTop(); + } + + + public int getStartAfterPadding() { + return getPaddingTop(); + } + + public int getTotalSpace() { + return getHeight() - getPaddingTop() - getPaddingBottom(); + } } /** @@ -11030,7 +11038,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, } } - boolean shouldIgnore() { + public boolean shouldIgnore() { return (mFlags & FLAG_IGNORE) != 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index ea7fdf5dc..b6b20485e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -63,7 +63,6 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.method.LinkMovementMethod; -import android.text.style.ForegroundColorSpan; import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.DisplayMetrics; @@ -101,6 +100,7 @@ import com.microsoft.appcenter.crashes.Crashes; import com.microsoft.appcenter.distribute.Distribute; import org.telegram.PhoneFormat.PhoneFormat; +import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -244,16 +244,22 @@ public class AndroidUtilities { return false; } - public static CharSequence ellipsizeCenterEnd(CharSequence str, String query, int availableWidth, TextPaint textPaint) { + public static CharSequence ellipsizeCenterEnd(CharSequence str, String query, int availableWidth, TextPaint textPaint, int maxSymbols) { try { - StaticLayout staticLayout = new StaticLayout(str, textPaint, Integer.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); int lastIndex = str.length(); + int startHighlightedIndex = str.toString().toLowerCase().indexOf(query); + + if (lastIndex > maxSymbols) { + str = str.subSequence(Math.max(0, startHighlightedIndex - maxSymbols / 2), Math.min(lastIndex, startHighlightedIndex + maxSymbols / 2)); + startHighlightedIndex -= Math.max(0, startHighlightedIndex - maxSymbols / 2); + lastIndex = str.length(); + } + StaticLayout staticLayout = new StaticLayout(str, textPaint, Integer.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); float endOfTextX = staticLayout.getPrimaryHorizontal(lastIndex); if (endOfTextX + textPaint.measureText("...") < availableWidth) { return str; } - int startHighlightedIndex = str.toString().toLowerCase().indexOf(query); int i = startHighlightedIndex + 1; while (i < str.length() - 1 && !Character.isWhitespace(str.charAt(i))) { i++; @@ -361,7 +367,7 @@ public class AndroidUtilities { return url; } - private static void gatherLinks(ArrayList links, Spannable s, Pattern pattern, String[] schemes, Linkify.MatchFilter matchFilter) { + private static void gatherLinks(ArrayList links, Spannable s, Pattern pattern, String[] schemes, Linkify.MatchFilter matchFilter, boolean internalOnly) { Matcher m = pattern.matcher(s); while (m.find()) { int start = m.start(); @@ -370,7 +376,11 @@ public class AndroidUtilities { if (matchFilter == null || matchFilter.acceptMatch(s, start, end)) { LinkSpec spec = new LinkSpec(); - spec.url = makeUrl(m.group(0), schemes, m); + String url = makeUrl(m.group(0), schemes, m); + if (internalOnly && !Browser.isInternalUrl(url, null)) { + continue; + } + spec.url = url; spec.start = start; spec.end = end; @@ -390,7 +400,11 @@ public class AndroidUtilities { }; public static boolean addLinks(Spannable text, int mask) { - if (text != null && containsUnsupportedCharacters(text.toString()) || mask == 0) { + return addLinks(text, mask, false); + } + + public static boolean addLinks(Spannable text, int mask, boolean internalOnly) { + if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) { return false; } final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class); @@ -398,11 +412,11 @@ public class AndroidUtilities { text.removeSpan(old[i]); } final ArrayList links = new ArrayList<>(); - if ((mask & Linkify.PHONE_NUMBERS) != 0) { + if (!internalOnly && (mask & Linkify.PHONE_NUMBERS) != 0) { Linkify.addLinks(text, Linkify.PHONE_NUMBERS); } if ((mask & Linkify.WEB_URLS) != 0) { - gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://"}, sUrlMatchFilter); + gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://"}, sUrlMatchFilter, internalOnly); } pruneOverlaps(links); if (links.size() == 0) { @@ -638,6 +652,14 @@ public class AndroidUtilities { adjustOwnerClassGuid = classGuid; } + public static void requestAdjustNothing(Activity activity, int classGuid) { + if (activity == null || isTablet()) { + return; + } + activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); + adjustOwnerClassGuid = classGuid; + } + public static void setAdjustResizeToNothing(Activity activity, int classGuid) { if (activity == null || isTablet()) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 71b8b1c80..f3b443a44 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -18,8 +18,8 @@ public class BuildVars { public static boolean LOGS_ENABLED = false; public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; - public static int BUILD_VERSION = 2103; - public static String BUILD_VERSION_STRING = "7.1.0"; + public static int BUILD_VERSION = 2129; + public static String BUILD_VERSION_STRING = "7.2.0"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; public static String APPCENTER_HASH = "a5b5c4f5-51da-dedc-9918-d9766a22ca7c"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index ff79750d9..67d6b5ef8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -251,7 +251,7 @@ public class ChatObject { public static boolean canAddBotsToChat(TLRPC.Chat chat) { if (isChannel(chat)) { - if (chat != null && chat.megagroup && (chat.admin_rights != null && (chat.admin_rights.post_messages || chat.admin_rights.add_admins) || chat.creator)) { + if (chat.megagroup && (chat.admin_rights != null && (chat.admin_rights.post_messages || chat.admin_rights.add_admins) || chat.creator)) { return true; } } else { @@ -273,7 +273,7 @@ public class ChatObject { public static boolean isCanWriteToChannel(int chatId, int currentAccount) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId); - return ChatObject.canSendMessages(chat) || chat != null && chat.megagroup; + return ChatObject.canSendMessages(chat) || chat.megagroup; } public static boolean canWriteToChat(TLRPC.Chat chat) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java index 44b253434..5581ccc11 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java @@ -768,12 +768,12 @@ public class DownloadController extends BaseController implements NotificationCe } if (downloadObject.object instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) downloadObject.object; - getFileLoader().cancelLoadFile(document); + getFileLoader().cancelLoadFile(document, true); } else if (downloadObject.object instanceof TLRPC.Photo) { TLRPC.Photo photo = (TLRPC.Photo) downloadObject.object; TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); if (photoSize != null) { - getFileLoader().cancelLoadFile(photoSize); + getFileLoader().cancelLoadFile(photoSize, true); } } } @@ -783,14 +783,14 @@ public class DownloadController extends BaseController implements NotificationCe if (objects.isEmpty()) { return; } - ArrayList queue = null; + ArrayList queue; if (type == AUTODOWNLOAD_TYPE_PHOTO) { queue = photoDownloadQueue; } else if (type == AUTODOWNLOAD_TYPE_AUDIO) { queue = audioDownloadQueue; } else if (type == AUTODOWNLOAD_TYPE_VIDEO) { queue = videoDownloadQueue; - } else if (type == AUTODOWNLOAD_TYPE_DOCUMENT) { + } else { queue = documentDownloadQueue; } for (int a = 0; a < objects.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java index 019ffffc5..bc440d0d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java @@ -803,6 +803,10 @@ public class EmojiData { return "\uD83C\uDF51".equals(emoji); } + public static boolean isCofinEmoji(String emoji) { + return "⚰️".equals(emoji); + } + static { for (int a = 0; a < emojiToFE0F.length; a++) { emojiToFE0FMap.put(emojiToFE0F[a], true); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/EmuDetector.java b/TMessagesProj/src/main/java/org/telegram/messenger/EmuDetector.java index 9ff49d9b7..adf89aba8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/EmuDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/EmuDetector.java @@ -8,6 +8,8 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Build; import androidx.core.content.ContextCompat; + +import android.os.Environment; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -34,6 +36,10 @@ public class EmuDetector { void onResult(boolean isEmulator); } + private enum EmulatorTypes { + GENY, ANDY, NOX, BLUE, PIPES, X86 + } + private static final String[] PHONE_NUMBERS = { "15555215554", "15555215556", "15555215558", "15555215560", "15555215562", "15555215564", "15555215566", "15555215568", "15555215570", "15555215572", "15555215574", "15555215576", @@ -81,7 +87,14 @@ public class EmuDetector { private static final String[] NOX_FILES = { "fstab.nox", "init.nox.rc", - "ueventd.nox.rc" + "ueventd.nox.rc", + "/BigNoxGameHD", + "/YSLauncher" + }; + + private static final String[] BLUE_FILES = { + "/Android/data/com.bluestacks.home", + "/Android/data/com.bluestacks.settings" }; private static final Property[] PROPERTIES = { @@ -132,6 +145,7 @@ public class EmuDetector { mListPackageName.add("com.google.android.launcher.layouts.genymotion"); mListPackageName.add("com.bluestacks"); mListPackageName.add("com.bignox.app"); + mListPackageName.add("com.vphone.launcher"); } public boolean isCheckTelephony() { @@ -185,23 +199,25 @@ public class EmuDetector { } private boolean checkBasic() { - boolean result = Build.FINGERPRINT.startsWith("generic") - || Build.MODEL.contains("google_sdk") - || Build.MODEL.toLowerCase().contains("droid4x") - || Build.MODEL.contains("Emulator") - || Build.MODEL.contains("Android SDK built for x86") - || Build.MANUFACTURER.contains("Genymotion") - || Build.HARDWARE.equals("goldfish") - || Build.HARDWARE.equals("vbox86") - || Build.PRODUCT.equals("sdk") - || Build.PRODUCT.equals("google_sdk") - || Build.PRODUCT.equals("sdk_x86") - || Build.PRODUCT.equals("vbox86p") - || Build.BOARD.toLowerCase().contains("nox") - || Build.BOOTLOADER.toLowerCase().contains("nox") - || Build.HARDWARE.toLowerCase().contains("nox") - || Build.PRODUCT.toLowerCase().contains("nox") - || Build.SERIAL.toLowerCase().contains("nox"); + boolean result = + Build.BOARD.toLowerCase().contains("nox") + || Build.BOOTLOADER.toLowerCase().contains("nox") + || Build.FINGERPRINT.startsWith("generic") + || Build.MODEL.toLowerCase().contains("google_sdk") + || Build.MODEL.toLowerCase().contains("droid4x") + || Build.MODEL.toLowerCase().contains("emulator") + || Build.MODEL.contains("Android SDK built for x86") + || Build.MANUFACTURER.toLowerCase().contains("genymotion") + || Build.HARDWARE.toLowerCase().contains("goldfish") + || Build.HARDWARE.toLowerCase().contains("vbox86") + || Build.HARDWARE.toLowerCase().contains("android_x86") + || Build.HARDWARE.toLowerCase().contains("nox") + || Build.PRODUCT.equals("sdk") + || Build.PRODUCT.equals("google_sdk") + || Build.PRODUCT.equals("sdk_x86") + || Build.PRODUCT.equals("vbox86p") + || Build.PRODUCT.toLowerCase().contains("nox") + || Build.SERIAL.toLowerCase().contains("nox"); if (result) { return true; @@ -216,13 +232,14 @@ public class EmuDetector { private boolean checkAdvanced() { return checkTelephony() - || checkFiles(GENY_FILES, "Geny") - || checkFiles(ANDY_FILES, "Andy") - || checkFiles(NOX_FILES, "Nox") + || checkFiles(GENY_FILES, EmulatorTypes.GENY) + || checkFiles(ANDY_FILES, EmulatorTypes.ANDY) + || checkFiles(NOX_FILES, EmulatorTypes.NOX) + || checkFiles(BLUE_FILES, EmulatorTypes.BLUE) || checkQEmuDrivers() - || checkFiles(PIPES, "Pipes") + || checkFiles(PIPES, EmulatorTypes.PIPES) || checkIp() - || (checkQEmuProps() && checkFiles(X86_FILES, "X86")); + || (checkQEmuProps() && checkFiles(X86_FILES, EmulatorTypes.X86)); } private boolean checkPackageName() { @@ -313,9 +330,18 @@ public class EmuDetector { return false; } - private boolean checkFiles(String[] targets, String type) { + private boolean checkFiles(String[] targets, EmulatorTypes type) { for (String pipe : targets) { - File qemu_file = new File(pipe); + File qemu_file; + if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + if ((pipe.contains("/") && type == EmulatorTypes.NOX) || type == EmulatorTypes.BLUE) { + qemu_file = new File(Environment.getExternalStorageDirectory() + pipe); + } else { + qemu_file = new File(pipe); + } + } else { + qemu_file = new File(pipe); + } if (qemu_file.exists()) { return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d0c8d0ee5..d32ee3706 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -1016,19 +1016,69 @@ public class FileLoadOperation { } public void cancel() { + cancel(false); + } + + public void cancel(boolean deleteFiles) { Utilities.stageQueue.postRunnable(() -> { - if (state == stateFinished || state == stateFailed) { - return; + if (state != stateFinished && state != stateFailed) { + if (requestInfos != null) { + for (int a = 0; a < requestInfos.size(); a++) { + RequestInfo requestInfo = requestInfos.get(a); + if (requestInfo.requestToken != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(requestInfo.requestToken, true); + } + } + } + onFail(false, 1); } - if (requestInfos != null) { - for (int a = 0; a < requestInfos.size(); a++) { - RequestInfo requestInfo = requestInfos.get(a); - if (requestInfo.requestToken != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(requestInfo.requestToken, true); + if (deleteFiles) { + if (cacheFileFinal != null) { + try { + if (!cacheFileFinal.delete()) { + cacheFileFinal.deleteOnExit(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + if (cacheFileTemp != null) { + try { + if (!cacheFileTemp.delete()) { + cacheFileTemp.deleteOnExit(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + if (cacheFileParts != null) { + try { + if (!cacheFileParts.delete()) { + cacheFileParts.deleteOnExit(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + if (cacheIvTemp != null) { + try { + if (!cacheIvTemp.delete()) { + cacheIvTemp.deleteOnExit(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + if (cacheFilePreload != null) { + try { + if (!cacheFilePreload.delete()) { + cacheFilePreload.deleteOnExit(); + } + } catch (Exception e) { + FileLog.e(e); } } } - onFail(false, 1); }); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 1c41de0e3..f622123a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -117,7 +117,7 @@ public class FileLoader extends BaseController { dir = mediaDirs.get(FileLoader.MEDIA_DIR_CACHE); } try { - if (!dir.isDirectory()) { + if (dir != null && !dir.isDirectory()) { dir.mkdirs(); } } catch (Exception e) { @@ -407,25 +407,23 @@ public class FileLoader extends BaseController { int queueType = operation.getQueueType(); LinkedList downloadQueue = getLoadOperationQueue(datacenterId, queueType); SparseIntArray count = getLoadOperationCount(queueType); - if (downloadQueue != null) { - int index = downloadQueue.indexOf(operation); - if (index >= 0) { - downloadQueue.remove(index); - if (operation.start()) { - count.put(datacenterId, count.get(datacenterId) + 1); - } - if (queueType == QUEUE_TYPE_FILE) { - if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) { - pauseCurrentFileLoadOperations(operation); - activeFileLoadOperation.add(operation); - } - } - } else { - pauseCurrentFileLoadOperations(operation); - operation.start(); - if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) { - activeFileLoadOperation.add(operation); + int index = downloadQueue.indexOf(operation); + if (index >= 0) { + downloadQueue.remove(index); + if (operation.start()) { + count.put(datacenterId, count.get(datacenterId) + 1); } + if (queueType == QUEUE_TYPE_FILE) { + if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) { + pauseCurrentFileLoadOperations(operation); + activeFileLoadOperation.add(operation); + } + } + } else { + pauseCurrentFileLoadOperations(operation); + operation.start(); + if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) { + activeFileLoadOperation.add(operation); } } } @@ -433,27 +431,49 @@ public class FileLoader extends BaseController { } public void cancelLoadFile(TLRPC.Document document) { - cancelLoadFile(document, null, null, null, null); + cancelLoadFile(document, false); + } + + public void cancelLoadFile(TLRPC.Document document, boolean deleteFile) { + cancelLoadFile(document, null, null, null, null, null, deleteFile); } public void cancelLoadFile(SecureDocument document) { - cancelLoadFile(null, document, null, null, null); + cancelLoadFile(null, document, null, null, null, null, false); } public void cancelLoadFile(WebFile document) { - cancelLoadFile(null, null, document, null, null); + cancelLoadFile(null, null, document, null, null, null, false); } public void cancelLoadFile(TLRPC.PhotoSize photo) { - cancelLoadFile(null, null, null, photo.location, null); + cancelLoadFile(photo, false); + } + + public void cancelLoadFile(TLRPC.PhotoSize photo, boolean deleteFile) { + cancelLoadFile(null, null, null, photo.location, null, null, deleteFile); } public void cancelLoadFile(TLRPC.FileLocation location, String ext) { - cancelLoadFile(null, null, null, location, ext); + cancelLoadFile(location, ext, false); } - private void cancelLoadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, final TLRPC.FileLocation location, final String locationExt) { - if (location == null && document == null && webDocument == null && secureDocument == null) { + public void cancelLoadFile(TLRPC.FileLocation location, String ext, boolean deleteFile) { + cancelLoadFile(null, null, null, location, ext, null, deleteFile); + } + + public void cancelLoadFile(String fileName) { + cancelLoadFile(null, null, null, null, null, fileName, true); + } + + public void cancelLoadFiles(ArrayList fileNames) { + for (int a = 0, N = fileNames.size(); a < N; a++) { + cancelLoadFile(null, null, null, null, null, fileNames.get(a), true); + } + } + + private void cancelLoadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, final TLRPC.FileLocation location, final String locationExt, String name, boolean deleteFile) { + if (location == null && document == null && webDocument == null && secureDocument == null && TextUtils.isEmpty(name)) { return; } final String fileName; @@ -466,10 +486,7 @@ public class FileLoader extends BaseController { } else if (webDocument != null) { fileName = getAttachFileName(webDocument); } else { - fileName = null; - } - if (fileName == null) { - return; + fileName = name; } loadOperationPathsUI.remove(fileName); fileLoaderQueue.postRunnable(() -> { @@ -485,7 +502,7 @@ public class FileLoader extends BaseController { if (queueType == QUEUE_TYPE_FILE) { activeFileLoadOperation.remove(operation); } - operation.cancel(); + operation.cancel(deleteFile); } }); } @@ -589,33 +606,29 @@ public class FileLoader extends BaseController { int queueType = operation.getQueueType(); LinkedList downloadQueue = getLoadOperationQueue(datacenterId, queueType); SparseIntArray count = getLoadOperationCount(queueType); - if (downloadQueue != null) { - int index = downloadQueue.indexOf(operation); - if (index >= 0) { - downloadQueue.remove(index); - if (stream != null) { - if (operation.start(stream, streamOffset, streamPriority)) { - count.put(datacenterId, count.get(datacenterId) + 1); + int index = downloadQueue.indexOf(operation); + if (index >= 0) { + downloadQueue.remove(index); + if (stream != null) { + if (operation.start(stream, streamOffset, streamPriority)) { + count.put(datacenterId, count.get(datacenterId) + 1); + } + if (queueType == QUEUE_TYPE_FILE) { + if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) { + pauseCurrentFileLoadOperations(operation); + activeFileLoadOperation.add(operation); } - if (queueType == QUEUE_TYPE_FILE) { - if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) { - if (stream != null) { - pauseCurrentFileLoadOperations(operation); - } - activeFileLoadOperation.add(operation); - } - } - } else { - downloadQueue.add(0, operation); } } else { - if (stream != null) { - pauseCurrentFileLoadOperations(operation); - } - operation.start(stream, streamOffset, streamPriority); - if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) { - activeFileLoadOperation.add(operation); - } + downloadQueue.add(0, operation); + } + } else { + if (stream != null) { + pauseCurrentFileLoadOperations(operation); + } + operation.start(stream, streamOffset, streamPriority); + if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) { + activeFileLoadOperation.add(operation); } } } @@ -626,14 +639,6 @@ public class FileLoader extends BaseController { File tempDir = getDirectory(MEDIA_DIR_CACHE); File storeDir = tempDir; int type = MEDIA_DIR_CACHE; - int queueType; - if (type == MEDIA_DIR_AUDIO) { - queueType = QUEUE_TYPE_AUDIO; - } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument)) { - queueType = QUEUE_TYPE_IMAGE; - } else { - queueType = QUEUE_TYPE_FILE; - } if (secureDocument != null) { operation = new FileLoadOperation(secureDocument); @@ -652,7 +657,9 @@ public class FileLoader extends BaseController { } } else if (webDocument != null) { operation = new FileLoadOperation(currentAccount, webDocument); - if (MessageObject.isVoiceWebDocument(webDocument)) { + if (webDocument.location != null) { + type = MEDIA_DIR_CACHE; + } else if (MessageObject.isVoiceWebDocument(webDocument)) { type = MEDIA_DIR_AUDIO; } else if (MessageObject.isVideoWebDocument(webDocument)) { type = MEDIA_DIR_VIDEO; @@ -662,6 +669,14 @@ public class FileLoader extends BaseController { type = MEDIA_DIR_DOCUMENT; } } + int queueType; + if (type == MEDIA_DIR_AUDIO) { + queueType = QUEUE_TYPE_AUDIO; + } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument)) { + queueType = QUEUE_TYPE_IMAGE; + } else { + queueType = QUEUE_TYPE_FILE; + } if (cacheType == 0 || cacheType == 10) { storeDir = getDirectory(type); } else if (cacheType == 2) { @@ -881,8 +896,6 @@ public class FileLoader extends BaseController { return getAttachFileName(sizeFull); } } - } else if (message.media instanceof TLRPC.TL_messageMediaInvoice) { - return getAttachFileName(((TLRPC.TL_messageMediaInvoice) message.media).photo); } } else if (message.media instanceof TLRPC.TL_messageMediaInvoice) { TLRPC.WebDocument document = ((TLRPC.TL_messageMediaInvoice) message.media).photo; @@ -966,7 +979,7 @@ public class FileLoader extends BaseController { } } else if (attach instanceof TLRPC.Photo) { TLRPC.PhotoSize photoSize = getClosestPhotoSizeWithSize(((TLRPC.Photo) attach).sizes, AndroidUtilities.getPhotoSize()); - return getPathToAttach(photoSize, ext, forceCache); + return getPathToAttach(photoSize, ext, false); } else if (attach instanceof TLRPC.PhotoSize) { TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) attach; if (photoSize instanceof TLRPC.TL_photoStrippedSize) { @@ -1127,15 +1140,13 @@ public class FileLoader extends BaseController { public static String getAttachFileName(TLObject attach, String ext) { if (attach instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) attach; - String docExt = null; - if (docExt == null) { - docExt = getDocumentFileName(document); - int idx; - if (docExt == null || (idx = docExt.lastIndexOf('.')) == -1) { - docExt = ""; - } else { - docExt = docExt.substring(idx); - } + String docExt; + docExt = getDocumentFileName(document); + int idx; + if ((idx = docExt.lastIndexOf('.')) == -1) { + docExt = ""; + } else { + docExt = docExt.substring(idx); } if (docExt.length() <= 1) { docExt = getExtensionByMimeType(document.mime_type); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 329353853..0f9f6fc0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -493,7 +493,7 @@ public class FileRefController extends BaseController { TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; mediaPhoto.id.file_reference = file_reference; } - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, (Boolean) requester.args[6])); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, null, (Boolean) requester.args[6])); } else if (requester.args[0] instanceof TLRPC.TL_messages_editMessage) { TLRPC.TL_messages_editMessage req = (TLRPC.TL_messages_editMessage) requester.args[0]; if (req.media instanceof TLRPC.TL_inputMediaDocument) { @@ -503,7 +503,7 @@ public class FileRefController extends BaseController { TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; mediaPhoto.id.file_reference = file_reference; } - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, (Boolean) requester.args[6])); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, null, (Boolean) requester.args[6])); } else if (requester.args[0] instanceof TLRPC.TL_messages_saveGif) { TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) requester.args[0]; req.id.file_reference = file_reference; @@ -554,7 +554,7 @@ public class FileRefController extends BaseController { AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(req, (ArrayList) objects[1], (ArrayList) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4], (Boolean) objects[5])); } } else if (args[0] instanceof TLRPC.TL_messages_sendMedia || args[0] instanceof TLRPC.TL_messages_editMessage) { - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null, (Boolean) args[6])); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null, null, (Boolean) args[6])); } else if (args[0] instanceof TLRPC.TL_messages_saveGif) { TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) args[0]; //do nothing diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 4a82969a0..db7132574 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -620,9 +620,6 @@ public class FileUploadOperation { startUploadRequest(); } } else { - if (finalRequest != null) { - FileLog.e("23123"); - } state = 4; delegate.didFailedUploadingFile(FileUploadOperation.this); cleanup(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java index abd24b0f8..0cc0219d7 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java @@ -339,7 +339,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { name = args[1]; } } else if (loc_key.startsWith("PINNED_")) { - supergroup = isGroup; + supergroup = channel_id != 0; pinned = true; } else if (loc_key.startsWith("CHANNEL_")) { channel = true; @@ -469,6 +469,16 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "MESSAGE_PLAYLIST": { + messageText = LocaleController.formatString("NotificationMessageFew", R.string.NotificationMessageFew, args[0], LocaleController.formatPluralString("MusicFiles", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } + case "MESSAGE_DOCS": { + messageText = LocaleController.formatString("NotificationMessageFew", R.string.NotificationMessageFew, args[0], LocaleController.formatPluralString("Files", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } case "MESSAGES": { messageText = LocaleController.formatString("NotificationMessageAlbum", R.string.NotificationMessageAlbum, args[0]); localMessage = true; @@ -564,6 +574,16 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "CHANNEL_MESSAGE_PLAYLIST": { + messageText = LocaleController.formatString("ChannelMessageFew", R.string.ChannelMessageFew, args[0], LocaleController.formatPluralString("MusicFiles", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } + case "CHANNEL_MESSAGE_DOCS": { + messageText = LocaleController.formatString("ChannelMessageFew", R.string.ChannelMessageFew, args[0], LocaleController.formatPluralString("Files", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } case "CHANNEL_MESSAGES": { messageText = LocaleController.formatString("ChannelMessageAlbum", R.string.ChannelMessageAlbum, args[0]); localMessage = true; @@ -710,152 +730,234 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "CHAT_MESSAGE_PLAYLIST": { + messageText = LocaleController.formatString("NotificationGroupFew", R.string.NotificationGroupFew, args[0], args[1], LocaleController.formatPluralString("MusicFiles", Utilities.parseInt(args[2]))); + localMessage = true; + break; + } + case "CHAT_MESSAGE_DOCS": { + messageText = LocaleController.formatString("NotificationGroupFew", R.string.NotificationGroupFew, args[0], args[1], LocaleController.formatPluralString("Files", Utilities.parseInt(args[2]))); + localMessage = true; + break; + } case "CHAT_MESSAGES": { messageText = LocaleController.formatString("NotificationGroupAlbum", R.string.NotificationGroupAlbum, args[0], args[1]); localMessage = true; break; } case "PINNED_TEXT": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, args[0], args[1], args[2]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, args[0], args[1]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, args[0], args[1], args[2]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, args[0], args[1]); + } } break; } case "PINNED_NOTEXT": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, args[0]); + } } break; } case "PINNED_PHOTO": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedPhoto", R.string.NotificationActionPinnedPhoto, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedPhotoUser", R.string.NotificationActionPinnedPhotoUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedPhotoChannel", R.string.NotificationActionPinnedPhotoChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedPhoto", R.string.NotificationActionPinnedPhoto, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedPhotoChannel", R.string.NotificationActionPinnedPhotoChannel, args[0]); + } } break; } case "PINNED_VIDEO": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedVideo", R.string.NotificationActionPinnedVideo, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedVideoUser", R.string.NotificationActionPinnedVideoUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedVideoChannel", R.string.NotificationActionPinnedVideoChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedVideo", R.string.NotificationActionPinnedVideo, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedVideoChannel", R.string.NotificationActionPinnedVideoChannel, args[0]); + } } break; } case "PINNED_ROUND": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedRound", R.string.NotificationActionPinnedRound, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedRoundUser", R.string.NotificationActionPinnedRoundUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedRoundChannel", R.string.NotificationActionPinnedRoundChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedRound", R.string.NotificationActionPinnedRound, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedRoundChannel", R.string.NotificationActionPinnedRoundChannel, args[0]); + } } break; } case "PINNED_DOC": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedFile", R.string.NotificationActionPinnedFile, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedFileUser", R.string.NotificationActionPinnedFileUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedFileChannel", R.string.NotificationActionPinnedFileChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedFile", R.string.NotificationActionPinnedFile, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedFileChannel", R.string.NotificationActionPinnedFileChannel, args[0]); + } } break; } case "PINNED_STICKER": { - if (isGroup) { - if (args.length > 2 && !TextUtils.isEmpty(args[2])) { - messageText = LocaleController.formatString("NotificationActionPinnedStickerEmoji", R.string.NotificationActionPinnedStickerEmoji, args[0], args[2], args[1]); + if (dialogId > 0) { + if (args.length > 1 && !TextUtils.isEmpty(args[1])) { + messageText = LocaleController.formatString("NotificationActionPinnedStickerEmojiUser", R.string.NotificationActionPinnedStickerEmojiUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedSticker", R.string.NotificationActionPinnedSticker, args[0], args[1]); + messageText = LocaleController.formatString("NotificationActionPinnedStickerUser", R.string.NotificationActionPinnedStickerUser, args[0]); } } else { - if (args.length > 1 && !TextUtils.isEmpty(args[1])) { - messageText = LocaleController.formatString("NotificationActionPinnedStickerEmojiChannel", R.string.NotificationActionPinnedStickerEmojiChannel, args[0], args[1]); + if (isGroup) { + if (args.length > 2 && !TextUtils.isEmpty(args[2])) { + messageText = LocaleController.formatString("NotificationActionPinnedStickerEmoji", R.string.NotificationActionPinnedStickerEmoji, args[0], args[2], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedSticker", R.string.NotificationActionPinnedSticker, args[0], args[1]); + } } else { - messageText = LocaleController.formatString("NotificationActionPinnedStickerChannel", R.string.NotificationActionPinnedStickerChannel, args[0]); + if (args.length > 1 && !TextUtils.isEmpty(args[1])) { + messageText = LocaleController.formatString("NotificationActionPinnedStickerEmojiChannel", R.string.NotificationActionPinnedStickerEmojiChannel, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedStickerChannel", R.string.NotificationActionPinnedStickerChannel, args[0]); + } } } break; } case "PINNED_AUDIO": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedVoice", R.string.NotificationActionPinnedVoice, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedVoiceUser", R.string.NotificationActionPinnedVoiceUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedVoiceChannel", R.string.NotificationActionPinnedVoiceChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedVoice", R.string.NotificationActionPinnedVoice, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedVoiceChannel", R.string.NotificationActionPinnedVoiceChannel, args[0]); + } } break; } case "PINNED_CONTACT": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, args[0], args[2], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedContactUser", R.string.NotificationActionPinnedContactUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, args[0], args[1]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, args[0], args[2], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, args[0], args[1]); + } } break; } case "PINNED_QUIZ": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, args[0], args[2], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, args[0], args[1]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, args[0], args[2], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, args[0], args[1]); + } } break; } case "PINNED_POLL": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, args[0], args[2], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, args[0], args[1]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, args[0], args[2], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, args[0], args[1]); + } } break; } case "PINNED_GEO": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedGeo", R.string.NotificationActionPinnedGeo, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGeoUser", R.string.NotificationActionPinnedGeoUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedGeoChannel", R.string.NotificationActionPinnedGeoChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedGeo", R.string.NotificationActionPinnedGeo, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGeoChannel", R.string.NotificationActionPinnedGeoChannel, args[0]); + } } break; } case "PINNED_GEOLIVE": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGeoLiveUser", R.string.NotificationActionPinnedGeoLiveUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, args[0]); + } } break; } case "PINNED_GAME": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedGame", R.string.NotificationActionPinnedGame, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGameUser", R.string.NotificationActionPinnedGameUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedGameChannel", R.string.NotificationActionPinnedGameChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedGame", R.string.NotificationActionPinnedGame, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGameChannel", R.string.NotificationActionPinnedGameChannel, args[0]); + } } break; } case "PINNED_GAME_SCORE": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedGameScore", R.string.NotificationActionPinnedGameScore, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGameScoreUser", R.string.NotificationActionPinnedGameScoreUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedGameScoreChannel", R.string.NotificationActionPinnedGameScoreChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedGameScore", R.string.NotificationActionPinnedGameScore, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGameScoreChannel", R.string.NotificationActionPinnedGameScoreChannel, args[0]); + } } break; } case "PINNED_INVOICE": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedInvoice", R.string.NotificationActionPinnedInvoice, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedInvoiceUser", R.string.NotificationActionPinnedInvoiceUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedInvoiceChannel", R.string.NotificationActionPinnedInvoiceChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedInvoice", R.string.NotificationActionPinnedInvoice, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedInvoiceChannel", R.string.NotificationActionPinnedInvoiceChannel, args[0]); + } } break; } case "PINNED_GIF": { - if (isGroup) { - messageText = LocaleController.formatString("NotificationActionPinnedGif", R.string.NotificationActionPinnedGif, args[0], args[1]); + if (dialogId > 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGifUser", R.string.NotificationActionPinnedGifUser, args[0], args[1]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedGifChannel", R.string.NotificationActionPinnedGifChannel, args[0]); + if (isGroup) { + messageText = LocaleController.formatString("NotificationActionPinnedGif", R.string.NotificationActionPinnedGif, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGifChannel", R.string.NotificationActionPinnedGifChannel, args[0]); + } } break; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 6de4d19f9..84c93ff88 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -38,6 +38,7 @@ import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.Point; import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.Components.SlotsDrawable; import org.telegram.ui.Components.SvgHelper; import org.telegram.ui.Components.ThemePreviewDrawable; @@ -828,7 +829,11 @@ public class ImageLoader { } RLottieDrawable lottieDrawable; if (diceEmoji != null) { - lottieDrawable = new RLottieDrawable(diceEmoji, w, h); + if ("\uD83C\uDFB0".equals(diceEmoji)) { + lottieDrawable = new SlotsDrawable(diceEmoji, w, h); + } else { + lottieDrawable = new RLottieDrawable(diceEmoji, w, h); + } } else { lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, precache, limitFps, colors); } @@ -1035,7 +1040,8 @@ public class ImageLoader { int photoW2 = opts.outWidth; int photoH2 = opts.outHeight; opts.inJustDecodeBounds = false; - float scaleFactor = Math.max(photoW2 / 200, photoH2 / 200); + int screenSize = Math.max(66, Math.min(AndroidUtilities.getRealScreenSize().x, AndroidUtilities.getRealScreenSize().y)); + float scaleFactor = (Math.min(photoH2, photoW2) / (float) screenSize) * 6f; if (scaleFactor < 1) { scaleFactor = 1; } @@ -1043,7 +1049,7 @@ public class ImageLoader { int sample = 1; do { sample *= 2; - } while (sample * 2 < scaleFactor); + } while (sample * 2 <= scaleFactor); opts.inSampleSize = sample; } else { opts.inSampleSize = (int) scaleFactor; @@ -2345,7 +2351,7 @@ public class ImageLoader { } else if (BuildVars.DEBUG_PRIVATE_VERSION) { String name = FileLoader.getDocumentFileName(imageLocation.document); if (name.endsWith(".svg")) { - img.imageType = FileLoader.IMAGE_TYPE_SVG_WHITE; + img.imageType = FileLoader.IMAGE_TYPE_SVG; } } } @@ -2377,7 +2383,7 @@ public class ImageLoader { } else if (BuildVars.DEBUG_PRIVATE_VERSION) { String name = FileLoader.getDocumentFileName(imageLocation.document); if (name.endsWith(".svg")) { - img.imageType = FileLoader.IMAGE_TYPE_SVG_WHITE; + img.imageType = FileLoader.IMAGE_TYPE_SVG; } } fileSize = document.size; @@ -2466,6 +2472,37 @@ public class ImageLoader { }); } + public void preloadArtwork(String athumbUrl) { + imageLoadQueue.postRunnable(() -> { + String ext = getHttpUrlExtension(athumbUrl, "jpg"); + String url = Utilities.MD5(athumbUrl) + "." + ext; + File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); + if (cacheFile.exists()) { + return; + } + ImageLocation imageLocation = ImageLocation.getForPath(athumbUrl); + CacheImage img = new CacheImage(); + img.type = ImageReceiver.TYPE_THUMB; + img.key = Utilities.MD5(athumbUrl); + img.filter = null; + img.imageLocation = imageLocation; + img.ext = ext; + img.parentObject = null; + if (imageLocation.imageType != 0) { + img.imageType = imageLocation.imageType; + } + img.url = url; + imageLoadingByUrl.put(url, img); + String file = Utilities.MD5(imageLocation.path); + File cacheDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); + img.tempFilePath = new File(cacheDir, file + "_temp.jpg"); + img.finalFilePath = cacheFile; + img.artworkTask = new ArtworkLoadTask(img); + artworkTasks.add(img.artworkTask); + runArtworkTasks(false); + }); + } + public void loadImageForImageReceiver(ImageReceiver imageReceiver) { if (imageReceiver == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 1e3849abb..8c9aaeeec 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -620,7 +620,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else if (bitmap instanceof RLottieDrawable) { RLottieDrawable fileDrawable = (RLottieDrawable) bitmap; fileDrawable.addParentView(parentView); - if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) { + if (allowStartLottieAnimation && (!fileDrawable.isHeavyDrawable() || currentOpenedLayerFlags == 0)) { fileDrawable.start(); } fileDrawable.setAllowDecodeSingleFrame(true); @@ -749,11 +749,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg setImage(temp.mediaLocation, temp.mediaFilter, temp.imageLocation, temp.imageFilter, temp.thumbLocation, temp.thumbFilter, temp.thumb, temp.size, temp.ext, temp.parentObject, temp.cacheType); temp.clear(); setImageBackup = temp; - if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) { - RLottieDrawable lottieDrawable = getLottieAnimation(); - if (lottieDrawable != null) { - lottieDrawable.start(); - } + RLottieDrawable lottieDrawable = getLottieAnimation(); + if (lottieDrawable != null && allowStartLottieAnimation && (!lottieDrawable.isHeavyDrawable() || currentOpenedLayerFlags == 0)) { + lottieDrawable.start(); } return true; } @@ -769,11 +767,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (setBackupImage()) { return true; } - if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) { - RLottieDrawable lottieDrawable = getLottieAnimation(); - if (lottieDrawable != null) { - lottieDrawable.start(); - } + RLottieDrawable lottieDrawable = getLottieAnimation(); + if (lottieDrawable != null && allowStartLottieAnimation && (!lottieDrawable.isHeavyDrawable() || currentOpenedLayerFlags == 0)) { + lottieDrawable.start(); } if (NotificationCenter.getGlobalInstance().isAnimationInProgress()) { didReceivedNotification(NotificationCenter.stopAllHeavyOperations, currentAccount, 512); @@ -1122,6 +1118,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } } + public void skipDraw() { + RLottieDrawable lottieDrawable = getLottieAnimation(); + if (lottieDrawable != null) { + lottieDrawable.setCurrentParentView(parentView); + lottieDrawable.updateCurrentFrame(); + } + } + public boolean draw(Canvas canvas) { try { Drawable drawable = null; @@ -1890,7 +1894,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else if (drawable instanceof RLottieDrawable) { RLottieDrawable fileDrawable = (RLottieDrawable) drawable; fileDrawable.addParentView(parentView); - if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) { + if (allowStartLottieAnimation && (!fileDrawable.isHeavyDrawable() || currentOpenedLayerFlags == 0)) { fileDrawable.start(); } fileDrawable.setAllowDecodeSingleFrame(true); @@ -2016,7 +2020,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentOpenedLayerFlags |= layer; if (currentOpenedLayerFlags != 0) { RLottieDrawable lottieDrawable = getLottieAnimation(); - if (lottieDrawable != null) { + if (lottieDrawable != null && lottieDrawable.isHeavyDrawable()) { lottieDrawable.stop(); } } @@ -2028,7 +2032,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentOpenedLayerFlags &=~ layer; if (currentOpenedLayerFlags == 0) { RLottieDrawable lottieDrawable = getLottieAnimation(); - if (allowStartLottieAnimation && lottieDrawable != null) { + if (allowStartLottieAnimation && lottieDrawable != null && lottieDrawable.isHeavyDrawable()) { lottieDrawable.start(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 5c33e1aaa..649c31e4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -233,9 +233,9 @@ public class LocaleController { "nl", "nn", "no", "sv", "af", "bg", "bn", "ca", "eu", "fur", "fy", "gu", "ha", "is", "ku", "lb", "ml", "mr", "nah", "ne", "om", "or", "pa", "pap", "ps", "so", "sq", "sw", "ta", "te", "tk", "ur", "zu", "mn", "gsw", "chr", "rm", "pt", "an", "ast"}, new PluralRules_One()); - addRules(new String[]{"cs", "sk"}, new PluralRules_Czech()); + addRules(new String[]{"cs", "sk", "sr", "hr", "bs"}, new PluralRules_Czech()); addRules(new String[]{"ff", "fr", "kab"}, new PluralRules_French()); - addRules(new String[]{"hr", "ru", "sr", "uk", "be", "bs", "sh"}, new PluralRules_Balkan()); + addRules(new String[]{"ru", "uk", "be", "sh"}, new PluralRules_Balkan()); addRules(new String[]{"lv"}, new PluralRules_Latvian()); addRules(new String[]{"lt"}, new PluralRules_Lithuanian()); addRules(new String[]{"pl"}, new PluralRules_Polish()); @@ -887,7 +887,7 @@ public class LocaleController { currentLocale = newLocale; currentLocaleInfo = localeInfo; - if (currentLocaleInfo != null && !TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) { + if (!TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) { currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode); } if (currentPluralRules == null) { @@ -934,12 +934,21 @@ public class LocaleController { } private String getStringInternal(String key, int res) { + return getStringInternal(key, null, res); + } + + private String getStringInternal(String key, String fallback, int res) { String value = BuildVars.USE_CLOUD_STRINGS ? localeValues.get(key) : null; if (value == null) { - try { - value = ApplicationLoader.applicationContext.getString(res); - } catch (Exception e) { - FileLog.e(e); + if (BuildVars.USE_CLOUD_STRINGS && fallback != null) { + value = localeValues.get(fallback); + } + if (value == null) { + try { + value = ApplicationLoader.applicationContext.getString(res); + } catch (Exception e) { + FileLog.e(e); + } } } if (value == null) { @@ -963,6 +972,10 @@ public class LocaleController { return getInstance().getStringInternal(key, res); } + public static String getString(String key, String fallback, int res) { + return getInstance().getStringInternal(key, fallback, res); + } + public static String getString(String key) { if (TextUtils.isEmpty(key)) { return "LOC_ERR:" + key; @@ -981,7 +994,7 @@ public class LocaleController { String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural)); param = key + "_" + param; int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName()); - return getString(param, resourceId); + return getString(param, key + "_other", resourceId); } public static String formatPluralString(String key, int plural) { @@ -991,7 +1004,7 @@ public class LocaleController { String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural)); param = key + "_" + param; int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName()); - return formatString(param, resourceId, plural); + return formatString(param, key + "_other", resourceId, plural); } public static String formatPluralStringComma(String key, int plural) { @@ -1007,6 +1020,9 @@ public class LocaleController { } String value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(param) : null; + if (value == null) { + value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(key + "_other") : null; + } if (value == null) { int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName()); value = ApplicationLoader.applicationContext.getString(resourceId); @@ -1025,10 +1041,19 @@ public class LocaleController { } public static String formatString(String key, int res, Object... args) { + return formatString(key, null, res, args); + } + + public static String formatString(String key, String fallback, int res, Object... args) { try { String value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(key) : null; if (value == null) { - value = ApplicationLoader.applicationContext.getString(res); + if (BuildVars.USE_CLOUD_STRINGS && fallback != null) { + value = getInstance().localeValues.get(fallback); + } + if (value == null) { + value = ApplicationLoader.applicationContext.getString(res); + } } if (getInstance().currentLocale != null) { @@ -1790,12 +1815,10 @@ public class LocaleController { valuesToSet.putAll(getLocaleFileStrings(localeInfo.getPathToFile())); } AndroidUtilities.runOnUIThread(() -> { - if (localeInfo != null) { - if (type == 0) { - localeInfo.version = difference.version; - } else { - localeInfo.baseVersion = difference.version; - } + if (type == 0) { + localeInfo.version = difference.version; + } else { + localeInfo.baseVersion = difference.version; } saveOtherLanguages(); try { @@ -1814,34 +1837,31 @@ public class LocaleController { } else { newLocale = new Locale(args[0], args[1]); } - if (newLocale != null) { - languageOverride = localeInfo.shortName; + languageOverride = localeInfo.shortName; - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("language", localeInfo.getKey()); - editor.commit(); + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("language", localeInfo.getKey()); + editor.commit(); + + localeValues = valuesToSet; + currentLocale = newLocale; + currentLocaleInfo = localeInfo; + if (!TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) { + currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode); } - if (newLocale != null) { - localeValues = valuesToSet; - currentLocale = newLocale; - currentLocaleInfo = localeInfo; - if (currentLocaleInfo != null && !TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) { - currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode); - } + if (currentPluralRules == null) { + currentPluralRules = allRules.get(currentLocale.getLanguage()); if (currentPluralRules == null) { - currentPluralRules = allRules.get(currentLocale.getLanguage()); - if (currentPluralRules == null) { - currentPluralRules = allRules.get("en"); - } + currentPluralRules = allRules.get("en"); } - changingConfiguration = true; - Locale.setDefault(currentLocale); - Configuration config = new Configuration(); - config.locale = currentLocale; - ApplicationLoader.applicationContext.getResources().updateConfiguration(config, ApplicationLoader.applicationContext.getResources().getDisplayMetrics()); - changingConfiguration = false; } + changingConfiguration = true; + Locale.setDefault(currentLocale); + Configuration config = new Configuration(); + config.locale = currentLocale; + ApplicationLoader.applicationContext.getResources().updateConfiguration(config, ApplicationLoader.applicationContext.getResources().getDisplayMetrics()); + changingConfiguration = false; } } catch (Exception e) { FileLog.e(e); @@ -1929,7 +1949,7 @@ public class LocaleController { } private void applyRemoteLanguage(LocaleInfo localeInfo, String langCode, boolean force, final int currentAccount) { - if (localeInfo == null || localeInfo != null && !localeInfo.isRemote() && !localeInfo.isUnofficial()) { + if (localeInfo == null || !localeInfo.isRemote() && !localeInfo.isUnofficial()) { return; } if (localeInfo.hasBaseLang() && (langCode == null || langCode.equals(localeInfo.baseLangCode))) { @@ -2819,32 +2839,49 @@ public class LocaleController { useImperialSystemType = null; } - public static String formatDistance(float distance, int type) { - if (useImperialSystemType == null) { - if (SharedConfig.distanceSystemType == 0) { - try { - TelephonyManager telephonyManager = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); - if (telephonyManager != null) { - String country = telephonyManager.getSimCountryIso().toUpperCase(); - useImperialSystemType = "US".equals(country) || "GB".equals(country) || "MM".equals(country) || "LR".equals(country); - } - } catch (Exception e) { - useImperialSystemType = false; - FileLog.e(e); - } - } else { - useImperialSystemType = SharedConfig.distanceSystemType == 2; - } + public static boolean getUseImperialSystemType() { + ensureImperialSystemInit(); + return useImperialSystemType; + } + + public static void ensureImperialSystemInit() { + if (useImperialSystemType != null) { + return; } - if (useImperialSystemType) { + if (SharedConfig.distanceSystemType == 0) { + try { + TelephonyManager telephonyManager = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); + if (telephonyManager != null) { + String country = telephonyManager.getSimCountryIso().toUpperCase(); + useImperialSystemType = "US".equals(country) || "GB".equals(country) || "MM".equals(country) || "LR".equals(country); + } + } catch (Exception e) { + useImperialSystemType = false; + FileLog.e(e); + } + } else { + useImperialSystemType = SharedConfig.distanceSystemType == 2; + } + } + + public static String formatDistance(float distance, int type) { + return formatDistance(distance, type, null); + } + + public static String formatDistance(float distance, int type, Boolean useImperial) { + ensureImperialSystemInit(); + boolean imperial = useImperial != null && useImperial || useImperial == null && useImperialSystemType; + if (imperial) { distance *= 3.28084f; if (distance < 1000) { switch (type) { case 0: return formatString("FootsAway", R.string.FootsAway, String.format("%d", (int) Math.max(1, distance))); case 1: - default: return formatString("FootsFromYou", R.string.FootsFromYou, String.format("%d", (int) Math.max(1, distance))); + case 2: + default: + return formatString("FootsShort", R.string.FootsShort, String.format("%d", (int) Math.max(1, distance))); } } else { String arg; @@ -2857,8 +2894,10 @@ public class LocaleController { case 0: return formatString("MilesAway", R.string.MilesAway, arg); case 1: - default: return formatString("MilesFromYou", R.string.MilesFromYou, arg); + default: + case 2: + return formatString("MilesShort", R.string.MilesShort, arg); } } @@ -2868,8 +2907,10 @@ public class LocaleController { case 0: return formatString("MetersAway2", R.string.MetersAway2, String.format("%d", (int) Math.max(1, distance))); case 1: - default: return formatString("MetersFromYou2", R.string.MetersFromYou2, String.format("%d", (int) Math.max(1, distance))); + case 2: + default: + return formatString("MetersShort", R.string.MetersShort, String.format("%d", (int) Math.max(1, distance))); } } else { String arg; @@ -2882,8 +2923,10 @@ public class LocaleController { case 0: return formatString("KMetersAway2", R.string.KMetersAway2, arg); case 1: - default: return formatString("KMetersFromYou2", R.string.KMetersFromYou2, arg); + case 2: + default: + return formatString("KMetersShort", R.string.KMetersShort, arg); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java index 84e0d1d00..a93151796 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java @@ -108,6 +108,8 @@ public class LocationController extends BaseController implements NotificationCe public int stopTime; public int period; public int account; + public int proximityMeters; + public int lastSentProximityMeters; public MessageObject messageObject; } @@ -211,6 +213,11 @@ public class LocationController extends BaseController implements NotificationCe if (!replaced) { messages.add(messageObject.messageOwner); } + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + int lowerId = (int) messageObject.getDialogId(); + if (lowerId > 0) { + setProximityLocation(messageObject.getDialogId(), 0, false); + } } } if (added) { @@ -379,7 +386,7 @@ public class LocationController extends BaseController implements NotificationCe float[] result = new float[1]; for (int a = 0; a < sharingLocations.size(); a++) { final SharingLocationInfo info = sharingLocations.get(a); - if (info.messageObject.messageOwner.media != null && info.messageObject.messageOwner.media.geo != null) { + if (info.messageObject.messageOwner.media != null && info.messageObject.messageOwner.media.geo != null && info.lastSentProximityMeters == info.proximityMeters) { int messageDate = info.messageObject.messageOwner.edit_date != 0 ? info.messageObject.messageOwner.edit_date : info.messageObject.messageOwner.date; TLRPC.GeoPoint point = info.messageObject.messageOwner.media.geo; if (Math.abs(date - messageDate) < 10) { @@ -398,6 +405,16 @@ public class LocationController extends BaseController implements NotificationCe req.media.geo_point = new TLRPC.TL_inputGeoPoint(); req.media.geo_point.lat = AndroidUtilities.fixLocationCoord(lastKnownLocation.getLatitude()); req.media.geo_point._long = AndroidUtilities.fixLocationCoord(lastKnownLocation.getLongitude()); + req.media.geo_point.accuracy_radius = (int) lastKnownLocation.getAccuracy(); + if (req.media.geo_point.accuracy_radius != 0) { + req.media.geo_point.flags |= 1; + } + if (info.lastSentProximityMeters != info.proximityMeters) { + req.media.proximity_notification_radius = info.proximityMeters; + req.media.flags |= 8; + } + req.media.heading = getHeading(lastKnownLocation); + req.media.flags |= 4; final int[] reqId = new int[1]; reqId[0] = getConnectionsManager().sendRequest(req, (response, error) -> { if (error != null) { @@ -417,6 +434,9 @@ public class LocationController extends BaseController implements NotificationCe } return; } + if ((req.flags & 8) != 0) { + info.lastSentProximityMeters = req.media.proximity_notification_radius; + } TLRPC.Updates updates = (TLRPC.Updates) response; boolean updated = false; for (int a1 = 0; a1 < updates.updates.size(); a1++) { @@ -563,11 +583,12 @@ public class LocationController extends BaseController implements NotificationCe return cachedNearbyChats; } - protected void addSharingLocation(long did, int mid, int period, TLRPC.Message message) { + protected void addSharingLocation(long did, int mid, int period, int radius, TLRPC.Message message) { final SharingLocationInfo info = new SharingLocationInfo(); info.did = did; info.mid = mid; info.period = period; + info.lastSentProximityMeters = info.proximityMeters = radius; info.account = currentAccount; info.messageObject = new MessageObject(currentAccount, message, false, false); info.stopTime = getConnectionsManager().getCurrentTime() + period; @@ -598,6 +619,41 @@ public class LocationController extends BaseController implements NotificationCe return sharingLocationsMapUI.get(did); } + public boolean setProximityLocation(long did, int meters, boolean broadcast) { + SharingLocationInfo info = sharingLocationsMapUI.get(did); + if (info != null) { + info.proximityMeters = meters; + } + getMessagesStorage().getStorageQueue().postRunnable(() -> { + try { + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE sharing_locations SET proximity = ? WHERE uid = ?"); + state.requery(); + state.bindInteger(1, meters); + state.bindLong(2, did); + state.step(); + state.dispose(); + } catch (Exception e) { + FileLog.e(e); + } + }); + if (broadcast) { + Utilities.stageQueue.postRunnable(() -> broadcastLastKnownLocation(true)); + } + return info != null; + } + + public static int getHeading(Location location) { + float val = location.getBearing(); + if (val > 0 && val < 1.0f) { + if (val < 0.5f) { + return 360; + } else { + return 1; + } + } + return (int) val; + } + private void loadSharingLocations() { getMessagesStorage().getStorageQueue().postRunnable(() -> { final ArrayList result = new ArrayList<>(); @@ -606,13 +662,14 @@ public class LocationController extends BaseController implements NotificationCe try { ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); - SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT uid, mid, date, period, message FROM sharing_locations WHERE 1"); + SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT uid, mid, date, period, message, proximity FROM sharing_locations WHERE 1"); while (cursor.next()) { SharingLocationInfo info = new SharingLocationInfo(); info.did = cursor.longValue(0); info.mid = cursor.intValue(1); info.stopTime = cursor.intValue(2); info.period = cursor.intValue(3); + info.proximityMeters = cursor.intValue(5); info.account = currentAccount; NativeByteBuffer data = cursor.byteBufferValue(4); if (data != null) { @@ -688,7 +745,7 @@ public class LocationController extends BaseController implements NotificationCe if (info == null) { return; } - SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO sharing_locations VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO sharing_locations VALUES(?, ?, ?, ?, ?, ?)"); state.requery(); NativeByteBuffer data = new NativeByteBuffer(info.messageObject.messageOwner.getObjectSize()); @@ -699,6 +756,7 @@ public class LocationController extends BaseController implements NotificationCe state.bindInteger(3, info.stopTime); state.bindInteger(4, info.period); state.bindByteBuffer(5, data); + state.bindInteger(6, info.proximityMeters); state.step(); state.dispose(); @@ -922,7 +980,7 @@ public class LocationController extends BaseController implements NotificationCe return; } ArrayList messages = locationsCache.get(dialogId); - if (messages.isEmpty() || messages == null) { + if (messages == null || messages.isEmpty()) { return; } Integer date = lastReadLocationTime.get(dialogId); @@ -977,9 +1035,7 @@ public class LocationController extends BaseController implements NotificationCe callbacks.remove(callback); } if (location == null) { - if (callback != null) { - callback.onLocationAddressAvailable(null, null, null); - } + callback.onLocationAddressAvailable(null, null, null); return; } @@ -1084,9 +1140,7 @@ public class LocationController extends BaseController implements NotificationCe final String displayNameFinal = displayName; AndroidUtilities.runOnUIThread(() -> { callbacks.remove(callback); - if (callback != null) { - callback.onLocationAddressAvailable(nameFinal, displayNameFinal, location); - } + callback.onLocationAddressAvailable(nameFinal, displayNameFinal, location); }); }, 300); callbacks.put(callback, fetchLocationRunnable); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java index 01c75cad6..73dceca78 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java @@ -94,6 +94,7 @@ public class LocationSharingService extends Service implements NotificationCente } String param; ArrayList infos = getInfos(); + String str; if (infos.size() == 1) { LocationController.SharingLocationInfo info = infos.get(0); int lower_id = (int) info.messageObject.getDialogId(); @@ -101,6 +102,7 @@ public class LocationSharingService extends Service implements NotificationCente if (lower_id > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id); param = UserObject.getFirstName(user); + str = LocaleController.getString("AttachLiveLocationIsSharing", R.string.AttachLiveLocationIsSharing); } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); if (chat != null) { @@ -108,13 +110,15 @@ public class LocationSharingService extends Service implements NotificationCente } else { param = ""; } + str = LocaleController.getString("AttachLiveLocationIsSharingChat", R.string.AttachLiveLocationIsSharingChat); } } else { param = LocaleController.formatPluralString("Chats", infos.size()); + str = LocaleController.getString("AttachLiveLocationIsSharingChats", R.string.AttachLiveLocationIsSharingChats); } - String str = String.format(LocaleController.getString("AttachLiveLocationIsSharing", R.string.AttachLiveLocationIsSharing), LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation), param); - builder.setTicker(str); - builder.setContentText(str); + String text = String.format(str, LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation), param); + builder.setTicker(text); + builder.setContentText(text); if (post) { NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(6, builder.build()); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 40ed827ec..89af8527b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -90,6 +90,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.CountDownLatch; public class MediaController implements AudioManager.OnAudioFocusChangeListener, NotificationCenter.NotificationCenterDelegate, SensorEventListener { @@ -474,6 +475,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private boolean isPaused = false; private VideoPlayer audioPlayer = null; + private VideoPlayer emojiSoundPlayer = null; + private int emojiSoundPlayerNum = 0; private boolean isStreamingCurrentAudio; private int playerNum; private String shouldSavePositionForCurrentAudio; @@ -2089,10 +2092,11 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } currentPlaylistNum = index; playMusicAgain = true; - if (playingMessageObject != null) { + MessageObject messageObject = playlist.get(currentPlaylistNum); + if (playingMessageObject != null && !isSamePlayingMessage(messageObject)) { playingMessageObject.resetPlayingProgress(); } - playMessage(playlist.get(currentPlaylistNum)); + playMessage(messageObject); } private void playNextMessageWithoutOrder(boolean byStop) { @@ -2583,6 +2587,91 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, }*/ } + public void playEmojiSound(AccountInstance accountInstance, String emoji, MessagesController.EmojiSound sound, boolean loadOnly) { + if (sound == null) { + return; + } + Utilities.stageQueue.postRunnable(() -> { + TLRPC.Document document = new TLRPC.TL_document(); + document.access_hash = sound.accessHash; + document.id = sound.id; + document.mime_type = "sound/ogg"; + document.file_reference = sound.fileReference; + document.dc_id = accountInstance.getConnectionsManager().getCurrentDatacenterId(); + File file = FileLoader.getPathToAttach(document, true); + if (file.exists()) { + if (loadOnly) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + try { + int tag = ++emojiSoundPlayerNum; + if (emojiSoundPlayer != null) { + emojiSoundPlayer.releasePlayer(true); + } + emojiSoundPlayer = new VideoPlayer(false); + emojiSoundPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { + @Override + public void onStateChanged(boolean playWhenReady, int playbackState) { + AndroidUtilities.runOnUIThread(() -> { + if (tag != emojiSoundPlayerNum) { + return; + } + if (playbackState == ExoPlayer.STATE_ENDED) { + if (emojiSoundPlayer != null) { + try { + emojiSoundPlayer.releasePlayer(true); + emojiSoundPlayer = null; + } catch (Exception e) { + FileLog.e(e); + } + } + } + }); + } + + @Override + public void onError(VideoPlayer player, Exception e) { + + } + + @Override + public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + + } + + @Override + public void onRenderedFirstFrame() { + + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + + @Override + public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { + return false; + } + }); + emojiSoundPlayer.preparePlayer(Uri.fromFile(file), "other"); + emojiSoundPlayer.setStreamType(AudioManager.STREAM_MUSIC); + emojiSoundPlayer.play(); + } catch (Exception e) { + FileLog.e(e); + if (emojiSoundPlayer != null) { + emojiSoundPlayer.releasePlayer(true); + emojiSoundPlayer = null; + } + } + }); + } else { + AndroidUtilities.runOnUIThread(() -> accountInstance.getFileLoader().loadFile(document, null, 1, 1)); + } + }); + } + public boolean playMessage(final MessageObject messageObject) { if (messageObject == null) { return false; @@ -3343,7 +3432,226 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, }); } + private static class MediaLoader implements NotificationCenter.NotificationCenterDelegate { + + private AccountInstance currentAccount; + private AlertDialog progressDialog; + private ArrayList messageObjects; + private HashMap loadingMessageObjects = new HashMap<>(); + private float finishedProgress; + private boolean cancelled; + private boolean finished; + private int copiedFiles; + private CountDownLatch waitingForFile; + private MessagesStorage.IntCallback onFinishRunnable; + private boolean isMusic; + + public MediaLoader(Context context, AccountInstance accountInstance, ArrayList messages, MessagesStorage.IntCallback onFinish) { + currentAccount = accountInstance; + messageObjects = messages; + onFinishRunnable = onFinish; + isMusic = messages.get(0).isMusic(); + currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.fileDidLoad); + currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.FileLoadProgressChanged); + currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.fileDidFailToLoad); + progressDialog = new AlertDialog(context, 2); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(true); + progressDialog.setOnCancelListener(d -> cancelled = true); + } + + public void start() { + AndroidUtilities.runOnUIThread(() -> { + if (!finished) { + progressDialog.show(); + } + }, 250); + + new Thread(() -> { + try { + File dir; + if (isMusic) { + dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); + } else { + dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + } + dir.mkdir(); + for (int b = 0, N = messageObjects.size(); b < N; b++) { + MessageObject message = messageObjects.get(b); + String name = message.getDocumentName(); + File destFile = new File(dir, name); + if (destFile.exists()) { + int idx = name.lastIndexOf('.'); + for (int a = 0; a < 10; a++) { + String newName; + if (idx != -1) { + newName = name.substring(0, idx) + "(" + (a + 1) + ")" + name.substring(idx); + } else { + newName = name + "(" + (a + 1) + ")"; + } + destFile = new File(dir, newName); + if (!destFile.exists()) { + break; + } + } + } + if (!destFile.exists()) { + destFile.createNewFile(); + } + String path = message.messageOwner.attachPath; + if (path != null && path.length() > 0) { + File temp = new File(path); + if (!temp.exists()) { + path = null; + } + } + if (path == null || path.length() == 0) { + path = FileLoader.getPathToMessage(message.messageOwner).toString(); + } + File sourceFile = new File(path); + if (!sourceFile.exists()) { + waitingForFile = new CountDownLatch(1); + addMessageToLoad(message); + waitingForFile.await(); + } + copyFile(sourceFile, destFile, message.getMimeType()); + } + checkIfFinished(); + } catch (Exception e) { + FileLog.e(e); + } + + }).start(); + } + + private void checkIfFinished() { + if (!loadingMessageObjects.isEmpty()) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + try { + if (progressDialog.isShowing()) { + progressDialog.dismiss(); + } else { + finished = true; + } + if (onFinishRunnable != null) { + AndroidUtilities.runOnUIThread(() -> onFinishRunnable.run(copiedFiles)); + } + } catch (Exception e) { + FileLog.e(e); + } + currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.fileDidLoad); + currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.FileLoadProgressChanged); + currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.fileDidFailToLoad); + }); + } + + private void addMessageToLoad(MessageObject messageObject) { + AndroidUtilities.runOnUIThread(() -> { + TLRPC.Document document = messageObject.getDocument(); + if (document == null) { + return; + } + String fileName = FileLoader.getAttachFileName(document); + loadingMessageObjects.put(fileName, messageObject); + currentAccount.getFileLoader().loadFile(document, messageObject, 1, 0); + }); + } + + private boolean copyFile(File sourceFile, File destFile, String mime) { + if (AndroidUtilities.isInternalUri(Uri.fromFile(sourceFile))) { + return false; + } + try (FileInputStream inputStream = new FileInputStream(sourceFile); FileChannel source = inputStream.getChannel(); FileChannel destination = new FileOutputStream(destFile).getChannel()) { + long size = source.size(); + try { + @SuppressLint("DiscouragedPrivateApi") Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$"); + int fdint = (Integer) getInt.invoke(inputStream.getFD()); + if (AndroidUtilities.isInternalUri(fdint)) { + if (progressDialog != null) { + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + return false; + } + } catch (Throwable e) { + FileLog.e(e); + } + long lastProgress = 0; + for (long a = 0; a < size; a += 4096) { + if (cancelled) { + break; + } + destination.transferFrom(source, a, Math.min(4096, size - a)); + } + if (!cancelled) { + if (isMusic) { + AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile)); + } else { + DownloadManager downloadManager = (DownloadManager) ApplicationLoader.applicationContext.getSystemService(Context.DOWNLOAD_SERVICE); + downloadManager.addCompletedDownload(destFile.getName(), destFile.getName(), false, mime, destFile.getAbsolutePath(), destFile.length(), true); + } + finishedProgress += 100.0f / messageObjects.size(); + final int progress = (int) (finishedProgress); + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.setProgress(progress); + } catch (Exception e) { + FileLog.e(e); + } + }); + copiedFiles++; + return true; + } + } catch (Exception e) { + FileLog.e(e); + } + destFile.delete(); + return false; + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailToLoad) { + String fileName = (String) args[0]; + if (loadingMessageObjects.remove(fileName) != null) { + waitingForFile.countDown(); + } + } else if (id == NotificationCenter.FileLoadProgressChanged) { + String fileName = (String) args[0]; + if (loadingMessageObjects.containsKey(fileName)) { + Long loadedSize = (Long) args[1]; + Long totalSize = (Long) args[2]; + float loadProgress = loadedSize / (float) totalSize; + final int progress = (int) (finishedProgress + loadProgress / messageObjects.size() * 100); + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.setProgress(progress); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + } + } + } + + public static void saveFilesFromMessages(Context context, AccountInstance accountInstance, ArrayList messageObjects, final MessagesStorage.IntCallback onSaved) { + new MediaLoader(context, accountInstance, messageObjects, onSaved).start(); + } + public static void saveFile(String fullPath, Context context, final int type, final String name, final String mime) { + saveFile(fullPath, context, type, name, mime, null); + } + + public static void saveFile(String fullPath, Context context, final int type, final String name, final String mime, final Runnable onSaved) { if (fullPath == null) { return; } @@ -3364,14 +3672,20 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, final boolean[] cancelled = new boolean[] {false}; if (sourceFile.exists()) { AlertDialog progressDialog = null; + final boolean[] finished = new boolean[1]; if (context != null && type != 0) { try { - progressDialog = new AlertDialog(context, 2); - progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); - progressDialog.setCanceledOnTouchOutside(false); - progressDialog.setCancelable(true); - progressDialog.setOnCancelListener(dialog -> cancelled[0] = true); - progressDialog.show(); + final AlertDialog dialog = new AlertDialog(context, 2); + dialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(true); + dialog.setOnCancelListener(d -> cancelled[0] = true); + AndroidUtilities.runOnUIThread(() -> { + if (!finished[0]) { + dialog.show(); + } + }, 250); + progressDialog = dialog; } catch (Exception e) { FileLog.e(e); } @@ -3471,6 +3785,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } else { AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile)); } + if (onSaved != null) { + AndroidUtilities.runOnUIThread(onSaved); + } } } catch (Exception e) { FileLog.e(e); @@ -3478,7 +3795,11 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, if (finalProgress != null) { AndroidUtilities.runOnUIThread(() -> { try { - finalProgress.dismiss(); + if (finalProgress.isShowing()) { + finalProgress.dismiss(); + } else { + finished[0] = true; + } } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index b56181dd0..4396fb4c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -199,6 +199,7 @@ public class MediaDataController extends BaseController { stickersLoaded[a] = false; } featuredStickerSets.clear(); + loadingPinnedMessages.clear(); loadFeaturedDate = 0; loadFeaturedHash = 0; allStickers.clear(); @@ -1871,7 +1872,7 @@ public class MediaDataController extends BaseController { } else { final StickerSetBulletinLayout bulletinLayout = new StickerSetBulletinLayout(context, stickerSetObject, toggle); final int finalCurrentIndex = currentIndex; - final Bulletin.UndoButton undoButton = new Bulletin.UndoButton(context).setUndoAction(() -> { + final Bulletin.UndoButton undoButton = new Bulletin.UndoButton(context, false).setUndoAction(() -> { stickerSet.archived = false; stickerSets[type].add(finalCurrentIndex, messages_stickerSet); @@ -1999,6 +2000,7 @@ public class MediaDataController extends BaseController { private int lastReqId; private int lastGuid; private TLRPC.User lastSearchUser; + private TLRPC.Chat lastSearchChat; private int[] messagesSearchCount = new int[]{0, 0}; private boolean[] messagesSearchEndReached = new boolean[]{false, false}; private ArrayList searchResultMessages = new ArrayList<>(); @@ -2030,8 +2032,8 @@ public class MediaDataController extends BaseController { return searchResultMessagesMap[mergeDialog ? 1 : 0].indexOfKey(messageId) >= 0; } - public void searchMessagesInChat(String query, final long dialogId, final long mergeDialogId, final int guid, final int direction, int replyMessageId, TLRPC.User user) { - searchMessagesInChat(query, dialogId, mergeDialogId, guid, direction, replyMessageId, false, user, true); + public void searchMessagesInChat(String query, final long dialogId, final long mergeDialogId, final int guid, final int direction, int replyMessageId, TLRPC.User user, TLRPC.Chat chat) { + searchMessagesInChat(query, dialogId, mergeDialogId, guid, direction, replyMessageId, false, user, chat, true); } public void jumpToSearchedMessage(int guid, int index) { @@ -2049,12 +2051,12 @@ public class MediaDataController extends BaseController { } int temp = searchResultMessages.size(); lastReturnedNum = searchResultMessages.size(); - searchMessagesInChat(null, lastDialogId, lastMergeDialogId, lastGuid, 1, lastReplyMessageId, false, lastSearchUser, false); + searchMessagesInChat(null, lastDialogId, lastMergeDialogId, lastGuid, 1, lastReplyMessageId, false, lastSearchUser, lastSearchChat, false); lastReturnedNum = temp; loadingMoreSearchMessages = true; } - private void searchMessagesInChat(String query, final long dialogId, final long mergeDialogId, final int guid, final int direction, int replyMessageId, final boolean internal, final TLRPC.User user, boolean jumpToMessage) { + private void searchMessagesInChat(String query, final long dialogId, final long mergeDialogId, final int guid, final int direction, int replyMessageId, final boolean internal, final TLRPC.User user, final TLRPC.Chat chat, boolean jumpToMessage) { int max_id = 0; long queryWithDialog = dialogId; boolean firstQuery = !internal; @@ -2131,9 +2133,12 @@ public class MediaDataController extends BaseController { req.peer = inputPeer; lastMergeDialogId = mergeDialogId; req.limit = 1; - req.q = query != null ? query : ""; + req.q = query; if (user != null) { - req.from_id = getMessagesController().getInputUser(user); + req.from_id = MessagesController.getInputPeer(user); + req.flags |= 1; + } else if (chat != null) { + req.from_id = MessagesController.getInputPeer(chat); req.flags |= 1; } req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); @@ -2144,7 +2149,7 @@ public class MediaDataController extends BaseController { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; messagesSearchEndReached[1] = res.messages.isEmpty(); messagesSearchCount[1] = res instanceof TLRPC.TL_messages_messagesSlice ? res.count : res.messages.size(); - searchMessagesInChat(req.q, dialogId, mergeDialogId, guid, direction, replyMessageId, true, user, jumpToMessage); + searchMessagesInChat(req.q, dialogId, mergeDialogId, guid, direction, replyMessageId, true, user, chat, jumpToMessage); } } }), ConnectionsManager.RequestFlagFailOnServerErrors); @@ -2163,12 +2168,16 @@ public class MediaDataController extends BaseController { lastGuid = guid; lastDialogId = dialogId; lastSearchUser = user; + lastSearchChat = chat; lastReplyMessageId = replyMessageId; req.limit = 21; req.q = query != null ? query : ""; req.offset_id = max_id; if (user != null) { - req.from_id = getMessagesController().getInputUser(user); + req.from_id = MessagesController.getInputPeer(user); + req.flags |= 1; + } else if (chat != null) { + req.from_id = MessagesController.getInputPeer(chat); req.flags |= 1; } if (lastReplyMessageId != 0) { @@ -2242,7 +2251,7 @@ public class MediaDataController extends BaseController { } } if (queryWithDialogFinal == dialogId && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) { - searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, jumpToMessage); + searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, chat, jumpToMessage); } } } @@ -3629,35 +3638,102 @@ public class MediaDataController extends BaseController { return 0; }; - public MessageObject loadPinnedMessage(final long dialogId, final int channelId, final int mid, boolean useQueue) { + private LongSparseArray loadingPinnedMessages = new LongSparseArray<>(); + + public void loadPinnedMessages(long dialogId, int maxId, int fallback) { + if (loadingPinnedMessages.indexOfKey(dialogId) >= 0) { + return; + } + loadingPinnedMessages.put(dialogId, true); + TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); + req.peer = getMessagesController().getInputPeer((int) dialogId); + req.limit = 40; + req.offset_id = maxId; + req.q = ""; + req.filter = new TLRPC.TL_inputMessagesFilterPinned(); + getConnectionsManager().sendRequest(req, (response, error) -> { + ArrayList ids = new ArrayList<>(); + HashMap messages = new HashMap<>(); + int totalCount = 0; + boolean endReached; + if (response instanceof TLRPC.messages_Messages) { + TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + final SparseArray usersDict = new SparseArray<>(); + for (int a = 0; a < res.users.size(); a++) { + TLRPC.User user = res.users.get(a); + usersDict.put(user.id, user); + } + final SparseArray chatsDict = new SparseArray<>(); + for (int a = 0; a < res.chats.size(); a++) { + TLRPC.Chat chat = res.chats.get(a); + chatsDict.put(chat.id, chat); + } + getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); + getMessagesController().putUsers(res.users, false); + getMessagesController().putChats(res.chats, false); + for (int a = 0, N = res.messages.size(); a < N; a++) { + TLRPC.Message message = res.messages.get(a); + if (message instanceof TLRPC.TL_messageService || message instanceof TLRPC.TL_messageEmpty) { + continue; + } + ids.add(message.id); + messages.put(message.id, new MessageObject(currentAccount, message, usersDict, chatsDict, false, false)); + } + if (fallback != 0 && ids.isEmpty()) { + ids.add(fallback); + } + endReached = res.messages.size() < req.limit; + totalCount = Math.max(res.count, res.messages.size()); + } else { + if (fallback != 0) { + ids.add(fallback); + totalCount = 1; + } + endReached = false; + } + getMessagesStorage().updatePinnedMessages(dialogId, ids, true, totalCount, maxId, endReached, messages); + AndroidUtilities.runOnUIThread(() -> loadingPinnedMessages.remove(dialogId)); + }); + } + + public ArrayList loadPinnedMessages(long dialogId, int channelId, ArrayList mids, boolean useQueue) { if (useQueue) { - getMessagesStorage().getStorageQueue().postRunnable(() -> loadPinnedMessageInternal(dialogId, channelId, mid, false)); + getMessagesStorage().getStorageQueue().postRunnable(() -> loadPinnedMessageInternal(dialogId, channelId, mids, false)); } else { - return loadPinnedMessageInternal(dialogId, channelId, mid, true); + return loadPinnedMessageInternal(dialogId, channelId, mids, true); } return null; } - private MessageObject loadPinnedMessageInternal(final long dialogId, final int channelId, final int mid, boolean returnValue) { + private ArrayList loadPinnedMessageInternal(long dialogId, int channelId, ArrayList mids, boolean returnValue) { try { - long messageId; + ArrayList midsCopy = new ArrayList<>(mids); + CharSequence longIds; if (channelId != 0) { - messageId = ((long) mid) | ((long) channelId) << 32; + StringBuilder builder = new StringBuilder(); + for (int a = 0, N = mids.size(); a < N; a++) { + long messageId = ((long) mids.get(a)) | ((long) channelId) << 32; + if (builder.length() != 0) { + builder.append(","); + } + builder.append(messageId); + } + longIds = builder; } else { - messageId = mid; + longIds = TextUtils.join(",", mids); } - TLRPC.Message result = null; + ArrayList results = new ArrayList<>(); final ArrayList users = new ArrayList<>(); final ArrayList chats = new ArrayList<>(); ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); - SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid = %d", messageId)); - if (cursor.next()) { + SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid IN (%s)", longIds)); + while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + TLRPC.Message result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); result.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); if (result.action instanceof TLRPC.TL_messageActionHistoryClear) { @@ -3667,55 +3743,66 @@ public class MediaDataController extends BaseController { result.date = cursor.intValue(2); result.dialog_id = dialogId; MessagesStorage.addUsersAndChatsFromMessage(result, usersToLoad, chatsToLoad); + results.add(result); } + midsCopy.remove((Integer) result.id); } } cursor.dispose(); - if (result == null) { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data FROM chat_pinned WHERE uid = %d", dialogId)); - if (cursor.next()) { + if (!midsCopy.isEmpty()) { + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data FROM chat_pinned_v2 WHERE uid = %d AND mid IN (%s)", dialogId, TextUtils.join(",", midsCopy))); + while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + TLRPC.Message result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); result.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); - if (result.id != mid || result.action instanceof TLRPC.TL_messageActionHistoryClear) { + if (result.action instanceof TLRPC.TL_messageActionHistoryClear) { result = null; } else { result.dialog_id = dialogId; MessagesStorage.addUsersAndChatsFromMessage(result, usersToLoad, chatsToLoad); + results.add(result); } + midsCopy.remove((Integer) result.id); } } cursor.dispose(); } - if (result == null) { + if (!midsCopy.isEmpty()) { if (channelId != 0) { final TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); - req.id.add(mid); + req.id = midsCopy; getConnectionsManager().sendRequest(req, (response, error) -> { boolean ok = false; if (error == null) { TLRPC.messages_Messages messagesRes = (TLRPC.messages_Messages) response; removeEmptyMessages(messagesRes.messages); if (!messagesRes.messages.isEmpty()) { + TLRPC.Chat chat = getMessagesController().getChat(channelId); + if (chat != null && chat.megagroup) { + for (int a = 0, N = messagesRes.messages.size(); a < N; a++) { + TLRPC.Message message = messagesRes.messages.get(a); + message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + } ImageLoader.saveMessagesThumbs(messagesRes.messages); - broadcastPinnedMessage(messagesRes.messages.get(0), messagesRes.users, messagesRes.chats, false, false); + broadcastPinnedMessage(messagesRes.messages, messagesRes.users, messagesRes.chats, false, false); getMessagesStorage().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true); - savePinnedMessage(messagesRes.messages.get(0)); + savePinnedMessages(dialogId, messagesRes.messages); ok = true; } } if (!ok) { - getMessagesStorage().updateChatPinnedMessage(channelId, 0); + getMessagesStorage().updatePinnedMessages(dialogId, req.id, false, -1, 0, false, null); } }); } else { final TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); - req.id.add(mid); + req.id = midsCopy; getConnectionsManager().sendRequest(req, (response, error) -> { boolean ok = false; if (error == null) { @@ -3723,20 +3810,21 @@ public class MediaDataController extends BaseController { removeEmptyMessages(messagesRes.messages); if (!messagesRes.messages.isEmpty()) { ImageLoader.saveMessagesThumbs(messagesRes.messages); - broadcastPinnedMessage(messagesRes.messages.get(0), messagesRes.users, messagesRes.chats, false, false); + broadcastPinnedMessage(messagesRes.messages, messagesRes.users, messagesRes.chats, false, false); getMessagesStorage().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true); - savePinnedMessage(messagesRes.messages.get(0)); + savePinnedMessages(dialogId, messagesRes.messages); ok = true; } } if (!ok) { - getMessagesStorage().updateChatPinnedMessage(channelId, 0); + getMessagesStorage().updatePinnedMessages(dialogId, req.id, false, -1, 0, false, null); } }); } - } else { + } + if (!results.isEmpty()) { if (returnValue) { - return broadcastPinnedMessage(result, users, chats, true, returnValue); + return broadcastPinnedMessage(results, users, chats, true, true); } else { if (!usersToLoad.isEmpty()) { getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), users); @@ -3744,7 +3832,7 @@ public class MediaDataController extends BaseController { if (!chatsToLoad.isEmpty()) { getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats); } - broadcastPinnedMessage(result, users, chats, true, false); + broadcastPinnedMessage(results, users, chats, true, false); } } } catch (Exception e) { @@ -3753,29 +3841,26 @@ public class MediaDataController extends BaseController { return null; } - private void savePinnedMessage(final TLRPC.Message result) { + private void savePinnedMessages(long dialogId, ArrayList arrayList) { + if (arrayList.isEmpty()) { + return; + } getMessagesStorage().getStorageQueue().postRunnable(() -> { try { - long dialogId; - if (result.peer_id.channel_id != 0) { - dialogId = -result.peer_id.channel_id; - } else if (result.peer_id.chat_id != 0) { - dialogId = -result.peer_id.chat_id; - } else if (result.peer_id.user_id != 0) { - dialogId = result.peer_id.user_id; - } else { - return; - } getMessagesStorage().getDatabase().beginTransaction(); - SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO chat_pinned VALUES(?, ?, ?)"); - NativeByteBuffer data = new NativeByteBuffer(result.getObjectSize()); - result.serializeToStream(data); - state.requery(); - state.bindLong(1, dialogId); - state.bindInteger(2, result.id); - state.bindByteBuffer(3, data); - state.step(); - data.reuse(); + //SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE chat_pinned_v2 SET data = ? WHERE uid = ? AND mid = ?"); + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO chat_pinned_v2 VALUES(?, ?, ?)"); + for (int a = 0, N = arrayList.size(); a < N; a++) { + TLRPC.Message message = arrayList.get(a); + NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); + state.requery(); + state.bindLong(1, dialogId); + state.bindInteger(2, message.id); + state.bindByteBuffer(3, data); + state.step(); + data.reuse(); + } state.dispose(); getMessagesStorage().getDatabase().commitTransaction(); } catch (Exception e) { @@ -3784,7 +3869,10 @@ public class MediaDataController extends BaseController { }); } - private MessageObject broadcastPinnedMessage(final TLRPC.Message result, final ArrayList users, final ArrayList chats, final boolean isCache, boolean returnValue) { + private ArrayList broadcastPinnedMessage(final ArrayList results, final ArrayList users, final ArrayList chats, final boolean isCache, boolean returnValue) { + if (results.isEmpty()) { + return null; + } final SparseArray usersDict = new SparseArray<>(); for (int a = 0; a < users.size(); a++) { TLRPC.User user = users.get(a); @@ -3795,13 +3883,24 @@ public class MediaDataController extends BaseController { TLRPC.Chat chat = chats.get(a); chatsDict.put(chat.id, chat); } + ArrayList messageObjects = new ArrayList<>(); if (returnValue) { - return new MessageObject(currentAccount, result, usersDict, chatsDict, false, false); + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().putUsers(users, isCache); + getMessagesController().putChats(chats, isCache); + }); + for (int a = 0, N = results.size(); a < N; a++) { + messageObjects.add(new MessageObject(currentAccount, results.get(a), usersDict, chatsDict, false, false)); + } + return messageObjects; } else { AndroidUtilities.runOnUIThread(() -> { getMessagesController().putUsers(users, isCache); getMessagesController().putChats(chats, isCache); - getNotificationCenter().postNotificationName(NotificationCenter.pinnedMessageDidLoad, new MessageObject(currentAccount, result, usersDict, chatsDict, false, false)); + for (int a = 0, N = results.size(); a < N; a++) { + messageObjects.add(new MessageObject(currentAccount, results.get(a), usersDict, chatsDict, false, false)); + } + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, messageObjects.get(0).getDialogId(), null, true, messageObjects, null, 0, -1, false)); }); } return null; @@ -3823,6 +3922,9 @@ public class MediaDataController extends BaseController { final LongSparseArray> replyMessageRandomOwners = new LongSparseArray<>(); for (int a = 0; a < messages.size(); a++) { MessageObject messageObject = messages.get(a); + if (messageObject == null) { + continue; + } if (messageObject.isReply() && messageObject.replyMessageObject == null) { long id = messageObject.messageOwner.reply_to.reply_to_random_id; ArrayList messageObjects = replyMessageRandomOwners.get(id); @@ -3899,6 +4001,9 @@ public class MediaDataController extends BaseController { final StringBuilder stringBuilder = new StringBuilder(); for (int a = 0; a < messages.size(); a++) { MessageObject messageObject = messages.get(a); + if (messageObject == null) { + continue; + } if (messageObject.getId() > 0 && messageObject.isReply() && messageObject.replyMessageObject == null) { int id = messageObject.messageOwner.reply_to.reply_to_msg_id; long messageId = id; @@ -4767,8 +4872,8 @@ public class MediaDataController extends BaseController { FileLog.e(e); } } + SparseArray threads = draftMessages.get(did); if (replyToMessage == null) { - SparseArray threads = draftMessages.get(did); if (threads != null) { threads.remove(threadId); if (threads.size() == 0) { @@ -4781,7 +4886,6 @@ public class MediaDataController extends BaseController { editor.remove("rt_" + did + "_" + threadId); } } else { - SparseArray threads = draftMessages.get(did); if (threads == null) { threads = new SparseArray<>(); draftMessages.put(did, threads); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index bed245799..a7448260e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -119,6 +119,8 @@ public class MessageObject { public boolean isRestrictedMessage; public long loadedFileSize; + public boolean animateComments; + public boolean loadingCancelled; public int stableId; @@ -167,6 +169,7 @@ public class MessageObject { public CharSequence vCardData; public ArrayList highlightedWords; + public String messageTrimmedToHighlight; static final String[] excludeWords = new String[] { " vs. ", @@ -255,10 +258,7 @@ public class MessageObject { if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { byte[] bytes = AndroidUtilities.decodeQuotedPrintable(AndroidUtilities.getStringBytes(currentData.company)); if (bytes != null && bytes.length != 0) { - String decodedName = new String(bytes, nameCharset); - if (decodedName != null) { - currentData.company = decodedName; - } + currentData.company = new String(bytes, nameCharset); } } currentData.company = currentData.company.replace(';', ' '); @@ -365,6 +365,7 @@ public class MessageObject { public ArrayList messages = new ArrayList<>(); public ArrayList posArray = new ArrayList<>(); public HashMap positions = new HashMap<>(); + public boolean isDocuments; private int maxSizeWidth = 800; @@ -418,6 +419,7 @@ public class MessageObject { int maxX = 0; boolean forceCalc = false; boolean needShare = false; + boolean isMusic = false; hasSibling = false; hasCaption = false; @@ -431,6 +433,9 @@ public class MessageObject { messageObject.messageOwner.from_id instanceof TLRPC.TL_peerUser && (messageObject.messageOwner.peer_id.channel_id != 0 || messageObject.messageOwner.peer_id.chat_id != 0 || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) ); + if (messageObject.isMusic() || messageObject.isDocument()) { + isDocuments = true; + } } TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); GroupedMessagePosition position = new GroupedMessagePosition(); @@ -458,6 +463,28 @@ public class MessageObject { hasCaption = true; } } + if (isDocuments) { + for (int a = 0; a < count; a++) { + GroupedMessagePosition pos = posArray.get(a); + pos.flags |= POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT; + if (a == 0) { + pos.flags |= POSITION_FLAG_TOP; + } else if (a == count - 1) { + pos.flags |= POSITION_FLAG_BOTTOM; + pos.last = true; + } + pos.edge = true; + pos.aspectRatio = 1.0f; + pos.minX = 0; + pos.maxX = 0; + pos.minY = (byte) a; + pos.maxY = (byte) a; + pos.spanSize = 1000; + pos.pw = maxSizeWidth; + pos.ph = 100; + } + return; + } if (needShare) { maxSizeWidth -= 50; @@ -542,7 +569,7 @@ public class MessageObject { position3.set(1, 1, 1, 1, width, secondHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); maxX = 1; } - } else if (count == 4) { + } else { GroupedMessagePosition position1 = posArray.get(0); GroupedMessagePosition position2 = posArray.get(1); GroupedMessagePosition position3 = posArray.get(2); @@ -997,9 +1024,7 @@ public class MessageObject { TLRPC.User fromUser = null; if (event.user_id > 0) { - if (fromUser == null) { - fromUser = MessagesController.getInstance(currentAccount).getUser(event.user_id); - } + fromUser = MessagesController.getInstance(currentAccount).getUser(event.user_id); } Calendar rightNow = new GregorianCalendar(); @@ -1168,10 +1193,8 @@ public class MessageObject { n = new TLRPC.TL_chatBannedRights(); } if (o.send_messages != n.send_messages) { - if (!added) { - rights.append('\n'); - added = true; - } + rights.append('\n'); + added = true; rights.append('\n').append(!n.send_messages ? '+' : '-').append(' '); rights.append(LocaleController.getString("EventLogRestrictedSendMessages", R.string.EventLogRestrictedSendMessages)); } @@ -1237,7 +1260,7 @@ public class MessageObject { TLRPC.User whoUser = MessagesController.getInstance(currentAccount).getUser(event.action.prev_participant.user_id); TLRPC.TL_chatBannedRights o = event.action.prev_participant.banned_rights; TLRPC.TL_chatBannedRights n = event.action.new_participant.banned_rights; - if (chat.megagroup && (n == null || !n.view_messages || n != null && o != null && n.until_date != o.until_date)) { + if (chat.megagroup && (n == null || !n.view_messages || o != null && n.until_date != o.until_date)) { StringBuilder rights; StringBuilder bannedDuration; if (n != null && !AndroidUtilities.isBannedForever(n)) { @@ -1291,10 +1314,8 @@ public class MessageObject { n = new TLRPC.TL_chatBannedRights(); } if (o.view_messages != n.view_messages) { - if (!added) { - rights.append('\n'); - added = true; - } + rights.append('\n'); + added = true; rights.append('\n').append(!n.view_messages ? '+' : '-').append(' '); rights.append(LocaleController.getString("EventLogRestrictedReadMessages", R.string.EventLogRestrictedReadMessages)); } @@ -1379,13 +1400,13 @@ public class MessageObject { } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionUpdatePinned) { if (fromUser != null && fromUser.id == 136817688 && event.action.message.fwd_from != null && event.action.message.fwd_from.from_id instanceof TLRPC.TL_peerChannel) { TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(event.action.message.fwd_from.from_id.channel_id); - if (event.action.message instanceof TLRPC.TL_messageEmpty) { + if (event.action.message instanceof TLRPC.TL_messageEmpty || !event.action.message.pinned) { messageText = replaceWithLink(LocaleController.getString("EventLogUnpinnedMessages", R.string.EventLogUnpinnedMessages), "un1", channel); } else { messageText = replaceWithLink(LocaleController.getString("EventLogPinnedMessages", R.string.EventLogPinnedMessages), "un1", channel); } } else { - if (event.action.message instanceof TLRPC.TL_messageEmpty) { + if (event.action.message instanceof TLRPC.TL_messageEmpty || !event.action.message.pinned) { messageText = replaceWithLink(LocaleController.getString("EventLogUnpinnedMessages", R.string.EventLogUnpinnedMessages), "un1", fromUser); } else { messageText = replaceWithLink(LocaleController.getString("EventLogPinnedMessages", R.string.EventLogPinnedMessages), "un1", fromUser); @@ -2110,6 +2131,9 @@ public class MessageObject { } public void measureInlineBotButtons() { + if (isRestrictedMessage) { + return; + } wantedBotKeyboardWidth = 0; if (messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty()) { Theme.createChatResources(null, true); @@ -2175,33 +2199,72 @@ public class MessageObject { return localType != 0; } + private TLRPC.User getUser(AbstractMap users, SparseArray sUsers, int uid) { + TLRPC.User user = null; + if (users != null) { + user = users.get(uid); + } else if (sUsers != null) { + user = sUsers.get(uid); + } + if (user == null) { + user = MessagesController.getInstance(currentAccount).getUser(uid); + } + return user; + } + + private TLRPC.Chat getChat(AbstractMap chats, SparseArray sChats, int cid) { + TLRPC.Chat chat = null; + if (chats != null) { + chat = chats.get(cid); + } else if (sChats != null) { + chat = sChats.get(cid); + } + if (chat == null) { + chat = MessagesController.getInstance(currentAccount).getChat(cid); + } + return chat; + } + private void updateMessageText(AbstractMap users, AbstractMap chats, SparseArray sUsers, SparseArray sChats) { TLRPC.User fromUser = null; TLRPC.Chat fromChat = null; if (messageOwner.from_id instanceof TLRPC.TL_peerUser) { - if (users != null) { - fromUser = users.get(messageOwner.from_id.user_id); - } else if (sUsers != null) { - fromUser = sUsers.get(messageOwner.from_id.user_id); - } - if (fromUser == null) { - fromUser = MessagesController.getInstance(currentAccount).getUser(messageOwner.from_id.user_id); - } + fromUser = getUser(users, sUsers, messageOwner.from_id.user_id); } else if (messageOwner.from_id instanceof TLRPC.TL_peerChannel) { - if (chats != null) { - fromChat = chats.get(messageOwner.from_id.channel_id); - } else if (sChats != null) { - fromChat = sChats.get(messageOwner.from_id.channel_id); - } - if (fromChat == null) { - fromChat = MessagesController.getInstance(currentAccount).getChat(messageOwner.from_id.channel_id); - } + fromChat = getChat(chats, sChats, messageOwner.from_id.channel_id); } TLObject fromObject = fromUser != null ? fromUser : fromChat; if (messageOwner instanceof TLRPC.TL_messageService) { if (messageOwner.action != null) { - if (messageOwner.action instanceof TLRPC.TL_messageActionCustomAction) { + if (messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + TLRPC.TL_messageActionGeoProximityReached action = (TLRPC.TL_messageActionGeoProximityReached) messageOwner.action; + int fromId = getPeerId(action.from_id); + TLObject from; + if (fromId > 0) { + from = getUser(users, sUsers, fromId); + } else { + from = getChat(chats, sChats, -fromId); + } + int toId = getPeerId(action.to_id); + int selfUserId = UserConfig.getInstance(currentAccount).getClientUserId(); + if (toId == selfUserId) { + messageText = replaceWithLink(LocaleController.formatString("ActionUserWithinRadius", R.string.ActionUserWithinRadius, LocaleController.formatDistance(action.distance, 2)), "un1", from); + } else { + TLObject to; + if (toId > 0) { + to = getUser(users, sUsers, toId); + } else { + to = getChat(chats, sChats, -toId); + } + if (fromId == selfUserId) { + messageText = replaceWithLink(LocaleController.formatString("ActionUserWithinYouRadius", R.string.ActionUserWithinYouRadius, LocaleController.formatDistance(action.distance, 2)), "un1", to); + } else { + messageText = replaceWithLink(LocaleController.formatString("ActionUserWithinOtherRadius", R.string.ActionUserWithinOtherRadius, LocaleController.formatDistance(action.distance, 2)), "un2", to); + messageText = replaceWithLink(messageText, "un1", from); + } + } + } else if (messageOwner.action instanceof TLRPC.TL_messageActionCustomAction) { messageText = messageOwner.action.message; } else if (messageOwner.action instanceof TLRPC.TL_messageActionChatCreate) { if (isOut()) { @@ -2625,7 +2688,7 @@ public class MessageObject { messageText = LocaleController.getString("AttachGif", R.string.AttachGif); } else { String name = FileLoader.getDocumentFileName(getDocument()); - if (name != null && name.length() > 0) { + if (!TextUtils.isEmpty(name)) { messageText = name; } else { messageText = LocaleController.getString("AttachDocument", R.string.AttachDocument); @@ -2698,7 +2761,7 @@ public class MessageObject { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { TLRPC.Document document = getDocument(); if (document != null && document.mime_type != null) { - if (isGifDocument(document)) { + if (isGifDocument(document, hasValidGroupId())) { type = 8; } else if (isSticker()) { type = TYPE_STICKER; @@ -2808,7 +2871,11 @@ public class MessageObject { } public static boolean isGifDocument(TLRPC.Document document) { - return document != null /*&& !document.thumbs.isEmpty()*/ && document.mime_type != null && (document.mime_type.equals("image/gif") || isNewGifDocument(document)); + return isGifDocument(document, false); + } + + public static boolean isGifDocument(TLRPC.Document document, boolean hasGroup) { + return document != null && document.mime_type != null && (document.mime_type.equals("image/gif") && !hasGroup || isNewGifDocument(document)); } public static boolean isDocumentHasThumb(TLRPC.Document document) { @@ -2856,7 +2923,7 @@ public class MessageObject { TLRPC.DocumentAttribute attribute = document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeVideo) { width = attribute.w; - height = attribute.w; + height = attribute.h; round = attribute.round_message; } } @@ -2947,7 +3014,7 @@ public class MessageObject { if (!update || photoThumbs == null) { photoThumbs = new ArrayList<>(); photoThumbs.addAll(emojiAnimatedSticker.thumbs); - } else if (photoThumbs != null && !photoThumbs.isEmpty()) { + } else if (!photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, emojiAnimatedSticker.thumbs); } photoThumbsObject = emojiAnimatedSticker; @@ -2982,7 +3049,7 @@ public class MessageObject { if (!update || photoThumbs == null) { photoThumbs = new ArrayList<>(); photoThumbs.addAll(document.thumbs); - } else if (photoThumbs != null && !photoThumbs.isEmpty()) { + } else if (!photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, document.thumbs); } photoThumbsObject = document; @@ -3381,13 +3448,13 @@ public class MessageObject { if (patternType == 1) { if (ch == '@') { url = new URLSpanNoUnderline("https://instagram.com/" + charSequence.subSequence(start + 1, end).toString()); - } else if (ch == '#') { + } else { url = new URLSpanNoUnderline("https://www.instagram.com/explore/tags/" + charSequence.subSequence(start + 1, end).toString()); } } else if (patternType == 2) { if (ch == '@') { url = new URLSpanNoUnderline("https://twitter.com/" + charSequence.subSequence(start + 1, end).toString()); - } else if (ch == '#') { + } else { url = new URLSpanNoUnderline("https://twitter.com/hashtag/" + charSequence.subSequence(start + 1, end).toString()); } } else { @@ -3465,7 +3532,7 @@ public class MessageObject { } public boolean hasValidGroupId() { - return getGroupId() != 0 && photoThumbs != null && !photoThumbs.isEmpty(); + return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || isMusic() || isDocument()); } public long getGroupIdForUse() { @@ -3481,16 +3548,20 @@ public class MessageObject { } public static void addLinks(boolean isOut, CharSequence messageText, boolean botCommands, boolean check) { + addLinks(isOut, messageText, botCommands, check, false); + } + + public static void addLinks(boolean isOut, CharSequence messageText, boolean botCommands, boolean check, boolean internalOnly) { if (messageText instanceof Spannable && containsUrls(messageText)) { if (messageText.length() < 1000) { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly); } catch (Exception e) { FileLog.e(e); } } else { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS); + AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS, internalOnly); } catch (Exception e) { FileLog.e(e); } @@ -3648,7 +3719,7 @@ public class MessageObject { b++; N2++; runs.add(b, r); - } else if (newRun.end >= run.end) { + } else { TextStyleSpan.TextStyleRun r = new TextStyleSpan.TextStyleRun(newRun); r.merge(run); r.end = run.end; @@ -4608,7 +4679,7 @@ public class MessageObject { if (message.media instanceof TLRPC.TL_messageMediaWebPage) { return isGifDocument(message.media.webpage.document); } - return message.media != null && isGifDocument(message.media.document); + return message.media != null && isGifDocument(message.media.document, message.grouped_id != 0); } public static boolean isRoundVideoMessage(TLRPC.Message message) { @@ -4903,6 +4974,10 @@ public class MessageObject { return isMusicMessage(messageOwner); } + public boolean isDocument() { + return getDocument() != null && !isVideo() && !isMusic() && !isVoice() && !isAnyKindOfSticker(); + } + public boolean isVoice() { return isVoiceMessage(messageOwner); } @@ -4919,6 +4994,10 @@ public class MessageObject { return isLiveLocationMessage(messageOwner); } + public boolean isExpiredLiveLocation(int date) { + return messageOwner.date + messageOwner.media.period <= date; + } + public boolean isGame() { return isGameMessage(messageOwner); } @@ -5498,9 +5577,7 @@ public class MessageObject { if (currentPhotoObject == null) { return; } - if (currentPhotoObject != null) { - mediaExists = FileLoader.getPathToAttach(currentPhotoObject, true).exists(); - } + mediaExists = FileLoader.getPathToAttach(currentPhotoObject, true).exists(); } else if (type == 11) { TLRPC.Photo photo = messageOwner.action.photo; if (photo == null || photo.video_sizes.isEmpty()) { @@ -5530,15 +5607,12 @@ public class MessageObject { searchForWords.addAll(Arrays.asList(words)); } if (getDocument() != null) { - String fileName = FileLoader.getDocumentFileName(getDocument()); - if (fileName != null) { - fileName = fileName.toLowerCase(); - if (fileName.contains(query) && !foundWords.contains(query)) { - foundWords.add(query); - } - String[] words = fileName.split("\\P{L}+"); - searchForWords.addAll(Arrays.asList(words)); + String fileName = FileLoader.getDocumentFileName(getDocument()).toLowerCase(); + if (fileName.contains(query) && !foundWords.contains(query)) { + foundWords.add(query); } + String[] words = fileName.split("\\P{L}+"); + searchForWords.addAll(Arrays.asList(words)); } if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage instanceof TLRPC.TL_webPage) { @@ -5600,7 +5674,22 @@ public class MessageObject { } if (!foundWords.isEmpty()) { highlightedWords = foundWords; + if (messageOwner.message != null) { + String str = messageOwner.message.replace('\n', ' ').replaceAll(" +", " ").trim(); + int lastIndex = str.length(); + int startHighlightedIndex = str.toLowerCase().indexOf(foundWords.get(0)); + int maxSymbols = 130; + if (startHighlightedIndex < 0) { + startHighlightedIndex = 0; + } + if (lastIndex > maxSymbols) { + int newStart = Math.max(0, startHighlightedIndex - maxSymbols / 2); + str = str.substring(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + maxSymbols / 2)); + } + messageTrimmedToHighlight = str; + } } + } public boolean hasHighlightedWords() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index eefc0c89d..a19dcf017 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -46,6 +46,7 @@ import org.telegram.ui.ProfileActivity; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -286,6 +287,7 @@ public class MessagesController extends BaseController implements NotificationCe public ArrayList gifSearchEmojies = new ArrayList<>(); public HashSet diceEmojies; public HashMap diceSuccess = new HashMap<>(); + public HashMap emojiSounds = new HashMap<>(); private SharedPreferences notificationsPreferences; private SharedPreferences mainPreferences; @@ -332,6 +334,33 @@ public class MessagesController extends BaseController implements NotificationCe } } + public static class EmojiSound { + public long id; + public long accessHash; + public byte[] fileReference; + + public EmojiSound(long i, long ah, String fr) { + id = i; + accessHash = ah; + fileReference = Base64.decode(fr, Base64.URL_SAFE); + } + + public EmojiSound(long i, long ah, byte[] fr) { + id = i; + accessHash = ah; + fileReference = fr; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof EmojiSound)) { + return false; + } + EmojiSound emojiSound = (EmojiSound) obj; + return id == emojiSound.id && accessHash == emojiSound.accessHash && Arrays.equals(fileReference, emojiSound.fileReference); + } + } + public static class DiceFrameSuccess { public int frame; public int num; @@ -523,7 +552,7 @@ public class MessagesController extends BaseController implements NotificationCe return 1; } else if (dialog1.pinned && !dialog2.pinned) { return -1; - } else if (dialog1.pinned && dialog2.pinned) { + } else if (dialog1.pinned) { if (dialog1.pinnedNum < dialog2.pinnedNum) { return 1; } else if (dialog1.pinnedNum > dialog2.pinnedNum) { @@ -711,6 +740,23 @@ public class MessagesController extends BaseController implements NotificationCe } } + text = mainPreferences.getString("emojiSounds", null); + if (text != null) { + try { + byte[] bytes = Base64.decode(text, Base64.DEFAULT); + if (bytes != null) { + SerializedData data = new SerializedData(bytes); + int count = data.readInt32(true); + for (int a = 0; a < count; a++) { + emojiSounds.put(data.readString(true), new EmojiSound(data.readInt64(true), data.readInt64(true), data.readByteArray(true))); + } + data.cleanup(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + text = mainPreferences.getString("gifSearchEmojies", null); if (text == null) { gifSearchEmojies.add("👍"); @@ -1017,14 +1063,14 @@ public class MessagesController extends BaseController implements NotificationCe } } + MessageObject newMsg = new_dialogMessage.get(value.id); if (currentDialog == null) { dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject != null && messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - if (messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); + dialogMessage.put(key, newMsg); + if (newMsg != null && newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); } } } else { @@ -1034,33 +1080,43 @@ public class MessagesController extends BaseController implements NotificationCe if (oldMsg != null && oldMsg.deleted || oldMsg == null || currentDialog.top_message > 0) { if (value.top_message >= currentDialog.top_message) { dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject != null && messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - if (messageObject != null && messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); - } - } + dialogMessage.put(key, newMsg); if (oldMsg != null) { - dialogMessagesByIds.remove(oldMsg.getId()); + if (oldMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(oldMsg.getId()); + } if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } } - } - } else { - MessageObject newMsg = new_dialogMessage.get(value.id); - if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) { - dialogs_dict.put(key, value); - dialogMessage.put(key, newMsg); if (newMsg != null && newMsg.messageOwner.peer_id.channel_id == 0) { + if (oldMsg != null && oldMsg.getId() == newMsg.getId()) { + newMsg.deleted = oldMsg.deleted; + } dialogMessagesByIds.put(newMsg.getId(), newMsg); - if (newMsg != null && newMsg.messageOwner.random_id != 0) { + if (newMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); } } - dialogMessagesByIds.remove(oldMsg.getId()); + } + } else { + if (newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) { + dialogs_dict.put(key, value); + dialogMessage.put(key, newMsg); + if (oldMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(oldMsg.getId()); + } + if (newMsg != null) { + if (oldMsg.getId() == newMsg.getId()) { + newMsg.deleted = oldMsg.deleted; + } + if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } + } + } if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } @@ -1404,6 +1460,56 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "emojies_sounds": { + try { + HashMap newEmojies = new HashMap<>(); + if (value.value instanceof TLRPC.TL_jsonObject) { + TLRPC.TL_jsonObject jsonObject = (TLRPC.TL_jsonObject) value.value; + for (int b = 0, N2 = jsonObject.value.size(); b < N2; b++) { + TLRPC.TL_jsonObjectValue val = jsonObject.value.get(b); + if (val.value instanceof TLRPC.TL_jsonObject) { + TLRPC.TL_jsonObject jsonObject2 = (TLRPC.TL_jsonObject) val.value; + long i = 0; + long ah = 0; + String fr = null; + for (int c = 0, N3 = jsonObject2.value.size(); c < N3; c++) { + TLRPC.TL_jsonObjectValue val2 = jsonObject2.value.get(c); + if (val2.value instanceof TLRPC.TL_jsonString) { + if ("id".equals(val2.key)) { + i = Utilities.parseLong(((TLRPC.TL_jsonString) val2.value).value); + } else if ("access_hash".equals(val2.key)) { + ah = Utilities.parseLong(((TLRPC.TL_jsonString) val2.value).value); + } else if ("file_reference_base64".equals(val2.key)) { + fr = ((TLRPC.TL_jsonString) val2.value).value; + } + } + } + if (i != 0 && ah != 0 && fr != null) { + newEmojies.put(val.key.replace("\uFE0F", ""), new EmojiSound(i, ah, fr)); + } + } + } + } + if (!emojiSounds.equals(newEmojies)) { + emojiSounds = newEmojies; + SerializedData serializedData = new SerializedData(); + serializedData.writeInt32(emojiSounds.size()); + for (HashMap.Entry entry : emojiSounds.entrySet()) { + serializedData.writeString(entry.getKey()); + EmojiSound emojiSound = entry.getValue(); + serializedData.writeInt64(emojiSound.id); + serializedData.writeInt64(emojiSound.accessHash); + serializedData.writeByteArray(emojiSound.fileReference); + } + editor.putString("emojiSounds", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT)); + serializedData.cleanup(); + changed = true; + } + } catch (Exception e) { + FileLog.e(e); + } + break; + } } } if (changed) { @@ -1764,8 +1870,6 @@ public class MessagesController extends BaseController implements NotificationCe } if (bigSize != null) { user.photo.photo_big = bigSize.location; - } else if (smallSize != null) { - user.photo.photo_small = smallSize.location; } getMessagesStorage().clearUserPhotos(user.id); ArrayList users = new ArrayList<>(); @@ -2016,8 +2120,8 @@ public class MessagesController extends BaseController implements NotificationCe getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); } obj = dialogMessagesByIds.get(msgId); - dialogMessagesByIds.remove(msgId); if (obj != null) { + dialogMessagesByIds.remove(msgId); dialogMessagesByIds.put(newMsgId, obj); } int lowerId = (int) (long) did; @@ -2032,12 +2136,14 @@ public class MessagesController extends BaseController implements NotificationCe } } else if (id == NotificationCenter.updateMessageMedia) { TLRPC.Message message = (TLRPC.Message) args[0]; - MessageObject existMessageObject = dialogMessagesByIds.get(message.id); - if (existMessageObject != null) { - existMessageObject.messageOwner.media = message.media; - if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { - existMessageObject.setType(); - getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); + if (message.peer_id.channel_id == 0) { + MessageObject existMessageObject = dialogMessagesByIds.get(message.id); + if (existMessageObject != null) { + existMessageObject.messageOwner.media = message.media; + if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { + existMessageObject.setType(); + getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); + } } } } @@ -2059,7 +2165,7 @@ public class MessagesController extends BaseController implements NotificationCe editor = emojiPreferences.edit(); editor.putLong("lastGifLoadTime", 0).putLong("lastStickersLoadTime", 0).putLong("lastStickersLoadTimeMask", 0).putLong("lastStickersLoadTimeFavs", 0).commit(); editor = mainPreferences.edit(); - editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName2").remove("webFileDatacenterId").remove("themehint").commit(); + editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName2").remove("webFileDatacenterId").remove("themehint").commit(); lastScheduledServerQueryTime.clear(); reloadingWebpages.clear(); @@ -2832,7 +2938,7 @@ public class MessagesController extends BaseController implements NotificationCe if (res.full_chat.stickerset != null) { getMediaDataController().getGroupStickerSetById(res.full_chat.stickerset); } - getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, res.full_chat, classGuid, false, null); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, res.full_chat, classGuid, false); if ((res.full_chat.flags & 2048) != 0) { TLRPC.Dialog dialog = dialogs_dict.get(-chat_id); if (dialog != null && dialog.folder_id != res.full_chat.folder_id) { @@ -2903,7 +3009,7 @@ public class MessagesController extends BaseController implements NotificationCe if (userFull.bot_info instanceof TLRPC.TL_botInfo) { getNotificationCenter().postNotificationName(NotificationCenter.botInfoDidLoad, userFull.bot_info, classGuid); } - getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, userFull, null); + getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, userFull); if ((userFull.flags & 2048) != 0) { TLRPC.Dialog dialog = dialogs_dict.get(user.id); if (dialog != null && dialog.folder_id != userFull.folder_id) { @@ -3008,7 +3114,7 @@ public class MessagesController extends BaseController implements NotificationCe if (dialogObj != null) { for (int a = 0; a < objects.size(); a++) { MessageObject obj = objects.get(a); - if (dialogObj != null && dialogObj.getId() == obj.getId()) { + if (dialogObj.getId() == obj.getId()) { dialogMessage.put(dialog_id, obj); if (obj.messageOwner.peer_id.channel_id == 0) { MessageObject obj2 = dialogMessagesByIds.get(obj.getId()); @@ -3818,13 +3924,13 @@ public class MessagesController extends BaseController implements NotificationCe } public void deleteMessages(ArrayList messages, ArrayList randoms, TLRPC.EncryptedChat encryptedChat, final long dialogId, final int channelId, boolean forAll, boolean scheduled, long taskId, TLObject taskRequest) { - if ((messages == null || messages.isEmpty()) && taskRequest == null) { + if ((messages == null || messages.isEmpty()) && taskId == 0) { return; } ArrayList toSend = null; if (taskId == 0) { toSend = new ArrayList<>(); - for (int a = 0; a < messages.size(); a++) { + for (int a = 0, N = messages.size(); a < N; a++) { Integer mid = messages.get(a); if (mid > 0) { toSend.add(mid); @@ -3952,16 +4058,41 @@ public class MessagesController extends BaseController implements NotificationCe } } - public void pinMessage(TLRPC.Chat chat, TLRPC.User user, int id, boolean notify) { + public void unpinAllMessages(TLRPC.Chat chat, TLRPC.User user) { + if (chat == null && user == null) { + return; + } + TLRPC.TL_messages_unpinAllMessages req = new TLRPC.TL_messages_unpinAllMessages(); + req.peer = getInputPeer(chat != null ? -chat.id : user.id); + getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + TLRPC.TL_messages_affectedHistory res = (TLRPC.TL_messages_affectedHistory) response; + if (ChatObject.isChannel(chat)) { + processNewChannelDifferenceParams(res.pts, res.pts_count, chat.id); + } else { + processNewDifferenceParams(-1, res.pts, -1, res.pts_count); + } + ArrayList ids = new ArrayList<>(); + getMessagesStorage().updatePinnedMessages(chat != null ? -chat.id : user.id, null, false, 0, 0, false, null); + } + }); + } + + public void pinMessage(TLRPC.Chat chat, TLRPC.User user, int id, boolean unpin, boolean oneSide, boolean notify) { if (chat == null && user == null) { return; } TLRPC.TL_messages_updatePinnedMessage req = new TLRPC.TL_messages_updatePinnedMessage(); req.peer = getInputPeer(chat != null ? -chat.id : user.id); req.id = id; + req.unpin = unpin; req.silent = !notify; + req.pm_oneside = oneSide; getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { + ArrayList ids = new ArrayList<>(); + ids.add(id); + getMessagesStorage().updatePinnedMessages(chat != null ? -chat.id : user.id, ids, !unpin, -1, 0, false, null); TLRPC.Updates updates = (TLRPC.Updates) response; processUpdates(updates, false); } @@ -4193,11 +4324,15 @@ public class MessagesController extends BaseController implements NotificationCe dialogMessage.remove(dialog.id); if (object != null) { lastMessageId = object.getId(); - dialogMessagesByIds.remove(object.getId()); + if (object.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(object.getId()); + } } else { lastMessageId = dialog.top_message; object = dialogMessagesByIds.get(dialog.top_message); - dialogMessagesByIds.remove(dialog.top_message); + if (object != null && object.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(dialog.top_message); + } } if (object != null && object.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(object.messageOwner.random_id); @@ -4363,7 +4498,7 @@ public class MessagesController extends BaseController implements NotificationCe } req.unsave = false; getConnectionsManager().sendRequest(req, (response, error) -> { - if (error != null && FileRefController.isFileRefError(error.text) && parentObject != null) { + if (error != null && FileRefController.isFileRefError(error.text)) { getFileRefController().requestReference(parentObject, req); } }); @@ -4384,7 +4519,7 @@ public class MessagesController extends BaseController implements NotificationCe req.unsave = false; req.attached = asMask; getConnectionsManager().sendRequest(req, (response, error) -> { - if (error != null && FileRefController.isFileRefError(error.text) && parentObject != null) { + if (error != null && FileRefController.isFileRefError(error.text)) { getFileRefController().requestReference(parentObject, req); } }); @@ -4413,29 +4548,36 @@ public class MessagesController extends BaseController implements NotificationCe })); } - public void processChatInfo(int chat_id, final TLRPC.ChatFull info, final ArrayList usersArr, final boolean fromCache, boolean force, final boolean byChannelUsers, final MessageObject pinnedMessageObject) { + public void processChatInfo(int chatId, final TLRPC.ChatFull info, final ArrayList usersArr, final boolean fromCache, boolean force, final boolean byChannelUsers, ArrayList pinnedMessages, HashMap pinnedMessagesMap, int totalPinnedCount, boolean pinnedEndReached) { AndroidUtilities.runOnUIThread(() -> { - if (fromCache && chat_id > 0 && !byChannelUsers) { - loadFullChat(chat_id, 0, force); + if (fromCache && chatId > 0 && !byChannelUsers) { + loadFullChat(chatId, 0, force); } if (info != null) { - if (fullChats.get(chat_id) == null) { - fullChats.put(chat_id, info); + if (fullChats.get(chatId) == null) { + fullChats.put(chatId, info); } putUsers(usersArr, fromCache); if (info.stickerset != null) { getMediaDataController().getGroupStickerSetById(info.stickerset); } - getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers, pinnedMessageObject); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers); + } + if (pinnedMessages != null) { + getNotificationCenter().postNotificationName(NotificationCenter.pinnedInfoDidLoad, (long) -chatId, pinnedMessages, pinnedMessagesMap, totalPinnedCount, pinnedEndReached); } }); } public void loadUserInfo(TLRPC.User user, boolean force, int classGuid) { - getMessagesStorage().loadUserInfo(user, force, classGuid); + loadUserInfo(user, force, classGuid, 0); } - public void processUserInfo(TLRPC.User user, final TLRPC.UserFull info, final boolean fromCache, boolean force, final MessageObject pinnedMessageObject, int classGuid) { + public void loadUserInfo(TLRPC.User user, boolean force, int classGuid, int fromMessageId) { + getMessagesStorage().loadUserInfo(user, force, classGuid, fromMessageId); + } + + public void processUserInfo(TLRPC.User user, TLRPC.UserFull info, boolean fromCache, boolean force, int classGuid, ArrayList pinnedMessages, HashMap pinnedMessagesMap, int totalPinnedCount, boolean pinnedEndReached) { AndroidUtilities.runOnUIThread(() -> { if (fromCache) { loadFullUser(user, classGuid, force); @@ -4449,7 +4591,10 @@ public class MessagesController extends BaseController implements NotificationCe blockePeers.delete(user.id); } } - getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, info, pinnedMessageObject); + getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, info); + } + if (pinnedMessages != null) { + getNotificationCenter().postNotificationName(NotificationCenter.pinnedInfoDidLoad, (long) user.id, pinnedMessages, pinnedMessagesMap, totalPinnedCount, pinnedEndReached); } }); } @@ -5221,14 +5366,27 @@ public class MessagesController extends BaseController implements NotificationCe } } - public void sendTyping(long dialogId, int threadMsgId, int action, int classGuid) { + public boolean sendTyping(long dialogId, int threadMsgId, int action, int classGuid) { if (action < 0 || action >= sendingTypings.length || dialogId == 0) { - return; + return false; } int lower_part = (int) dialogId; if (lower_part < 0) { if (ChatObject.shouldSendAnonymously(getChat(-lower_part))) { - return; + return false; + } + } else { + TLRPC.User user = getUser(lower_part); + if (user != null) { + if (user.id == getUserConfig().getClientUserId()) { + return false; + } + if (user.status != null && user.status.expires != -100 && !onlinePrivacy.containsKey(user.id)) { + int time = getConnectionsManager().getCurrentTime(); + if (user.status.expires <= time - 30) { + return false; + } + } } } LongSparseArray> dialogs = sendingTypings[action]; @@ -5240,7 +5398,7 @@ public class MessagesController extends BaseController implements NotificationCe dialogs.put(dialogId, threads = new SparseArray<>()); } if (threads.get(threadMsgId) != null) { - return; + return false; } int high_id = (int) (dialogId >> 32); if (lower_part != 0) { @@ -5253,11 +5411,11 @@ public class MessagesController extends BaseController implements NotificationCe if (req.peer instanceof TLRPC.TL_inputPeerChannel) { TLRPC.Chat chat = getChat(req.peer.channel_id); if (chat == null || !chat.megagroup) { - return; + return false; } } if (req.peer == null) { - return; + return false; } if (action == 0) { req.action = new TLRPC.TL_sendMessageTypingAction(); @@ -5287,7 +5445,7 @@ public class MessagesController extends BaseController implements NotificationCe } } else { if (action != 0) { - return; + return false; } TLRPC.EncryptedChat chat = getEncryptedChat(high_id); if (chat.auth_key != null && chat.auth_key.length > 1 && chat instanceof TLRPC.TL_encryptedChat) { @@ -5303,6 +5461,7 @@ public class MessagesController extends BaseController implements NotificationCe } } } + return true; } protected void removeDeletedMessagesFromArray(final long dialog_id, ArrayList messages) { @@ -5320,24 +5479,24 @@ public class MessagesController extends BaseController implements NotificationCe } } - public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int threadMessageId, int replyFirstUnread, int loadIndex) { - loadMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, threadMessageId, loadIndex, threadMessageId != 0 ? replyFirstUnread : 0, 0, 0, false, 0); + public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, int mode, int threadMessageId, int replyFirstUnread, int loadIndex) { + loadMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, mode, threadMessageId, loadIndex, threadMessageId != 0 ? replyFirstUnread : 0, 0, 0, false, 0); } - public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount) { - loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true); + public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, int mode, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount) { + loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true); } - private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int minDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean loadDialog) { + private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int minDate, int classGuid, int load_type, int last_message_id, boolean isChannel, int mode, int threadMessageId, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean loadDialog) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("load messages in chat " + dialogId + " count " + count + " max_id " + max_id + " cache " + fromCache + " mindate = " + minDate + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " scheduled " + scheduled + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer); + FileLog.d("load messages in chat " + dialogId + " count " + count + " max_id " + max_id + " cache " + fromCache + " mindate = " + minDate + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " mode " + mode + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer); } int lower_part = (int) dialogId; - if (threadMessageId == 0 && (fromCache || lower_part == 0)) { - getMessagesStorage().getMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, minDate, classGuid, load_type, isChannel, scheduled, threadMessageId, loadIndex); + if (threadMessageId == 0 && mode != 2 && (fromCache || lower_part == 0)) { + getMessagesStorage().getMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, minDate, classGuid, load_type, isChannel, mode == 1, threadMessageId, loadIndex); } else { if (threadMessageId != 0) { - if (scheduled) { + if (mode != 0) { return; } TLRPC.TL_messages_getReplies req = new TLRPC.TL_messages_getReplies(); @@ -5391,13 +5550,15 @@ public class MessagesController extends BaseController implements NotificationCe } } } - processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, fnid, last_message_id, unread_count, last_date, load_type, isChannel, false, false, threadMessageId, loadIndex, queryFromServer, mentionsCount); + processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, fnid, last_message_id, unread_count, last_date, load_type, isChannel, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount); } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); } }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); - } else if (scheduled) { + } else if (mode == 2) { + + } else if (mode == 1) { TLRPC.TL_messages_getScheduledHistory req = new TLRPC.TL_messages_getScheduledHistory(); req.peer = getInputPeer(lower_part); req.hash = minDate; @@ -5418,7 +5579,7 @@ public class MessagesController extends BaseController implements NotificationCe } } } - processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, true, threadMessageId, loadIndex, queryFromServer, mentionsCount); + processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, mode, threadMessageId, loadIndex, queryFromServer, mentionsCount); } }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); @@ -5445,7 +5606,7 @@ public class MessagesController extends BaseController implements NotificationCe getMessagesStorage().putDialogs(dialogs, 0); } - loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, isChannel, false, threadMessageId, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false); + loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, isChannel, 0, threadMessageId, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false); } } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); @@ -5493,7 +5654,7 @@ public class MessagesController extends BaseController implements NotificationCe } } } - processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, false, threadMessageId, loadIndex, queryFromServer, mentionsCount); + processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, 0, threadMessageId, loadIndex, queryFromServer, mentionsCount); } else { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error)); } @@ -5552,7 +5713,7 @@ public class MessagesController extends BaseController implements NotificationCe } public void processLoadedMessages(TLRPC.messages_Messages messagesRes, long dialogId, long mergeDialogId, int count, int max_id, int offset_date, boolean isCache, int classGuid, - int first_unread, int last_message_id, int unread_count, int last_date, int load_type, boolean isChannel, boolean isEnd, boolean scheduled, int threadMessageId, int loadIndex, boolean queryFromServer, int mentionsCount) { + int first_unread, int last_message_id, int unread_count, int last_date, int load_type, boolean isChannel, boolean isEnd, int mode, int threadMessageId, int loadIndex, boolean queryFromServer, int mentionsCount) { if (BuildVars.LOGS_ENABLED) { FileLog.d("processLoadedMessages size " + messagesRes.messages.size() + " in chat " + dialogId + " count " + count + " max_id " + max_id + " cache " + isCache + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " isChannel " + isChannel + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer); } @@ -5560,7 +5721,7 @@ public class MessagesController extends BaseController implements NotificationCe boolean isMegagroup = false; if (messagesRes instanceof TLRPC.TL_messages_channelMessages) { int channelId = -(int) dialogId; - if (!scheduled && threadMessageId == 0) { + if (mode == 0 && threadMessageId == 0) { int channelPts = channelsPts.get(channelId); if (channelPts == 0) { channelPts = getMessagesStorage().getChannelPtsSync(channelId); @@ -5590,9 +5751,11 @@ public class MessagesController extends BaseController implements NotificationCe } boolean isInitialLoading = offset_date == 0 && max_id == 0; - if (high_id != 1 && lower_id != 0 && isCache && ((messagesRes.messages.size() == 0 && (!isInitialLoading || (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 60 * 1000)) || scheduled && (SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialogId, 0L)) > 60 * 1000)) { + if (high_id != 1 && lower_id != 0 && isCache && ((messagesRes.messages.size() == 0 && (!isInitialLoading || (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 60 * 1000)) || mode == 1 && (SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialogId, 0L)) > 60 * 1000)) { int hash; - if (scheduled) { + if (mode == 2) { + hash = 0; + } else if (mode == 1) { lastScheduledServerQueryTime.put(dialogId, SystemClock.elapsedRealtime()); long h = 0; for (int a = 0, N = messagesRes.messages.size(); a < N; a++) { @@ -5609,7 +5772,7 @@ public class MessagesController extends BaseController implements NotificationCe lastServerQueryTime.put(dialogId, SystemClock.elapsedRealtime()); hash = 0; } - AndroidUtilities.runOnUIThread(() -> loadMessages(dialogId, mergeDialogId, false, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, isChannel, scheduled, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount)); + AndroidUtilities.runOnUIThread(() -> loadMessages(dialogId, mergeDialogId, false, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, isChannel, mode, threadMessageId, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount)); if (messagesRes.messages.isEmpty()) { return; } @@ -5644,7 +5807,7 @@ public class MessagesController extends BaseController implements NotificationCe message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; } - if (!scheduled) { + if (mode == 0) { if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) { TLRPC.User user = usersDict.get(message.action.user_id); if (user != null && user.bot) { @@ -5664,7 +5827,7 @@ public class MessagesController extends BaseController implements NotificationCe } } if (threadMessageId == 0) { - getMessagesStorage().putMessages(messagesRes, dialogId, load_type, max_id, createDialog, scheduled); + getMessagesStorage().putMessages(messagesRes, dialogId, load_type, max_id, createDialog, mode == 1); } } @@ -5676,7 +5839,7 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.Message message = messagesRes.messages.get(a); message.dialog_id = dialogId; MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true, true); - messageObject.scheduled = scheduled; + messageObject.scheduled = mode == 1; objects.add(messageObject); if (isCache) { if (message.legacy && message.layer < TLRPC.LAYER) { @@ -5704,7 +5867,7 @@ public class MessagesController extends BaseController implements NotificationCe putUsers(messagesRes.users, isCache); putChats(messagesRes.chats, isCache); int first_unread_final; - if (scheduled) { + if (mode == 1) { first_unread_final = 0; } else { first_unread_final = Integer.MAX_VALUE; @@ -5720,22 +5883,22 @@ public class MessagesController extends BaseController implements NotificationCe first_unread_final = first_unread; } } - if (scheduled && count == 1) { + if (mode == 1 && count == 1) { getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialogId, objects.size()); } if ((int) dialogId != 0) { int finalFirst_unread_final = first_unread_final; - getMediaDataController().loadReplyMessagesForMessages(objects, dialogId, scheduled, () -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, finalFirst_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled)); + getMediaDataController().loadReplyMessagesForMessages(objects, dialogId, mode == 1, () -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, finalFirst_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, mode)); } else { - getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, mode); } if (!messagesToReload.isEmpty()) { - reloadMessages(messagesToReload, dialogId, scheduled); + reloadMessages(messagesToReload, dialogId, mode == 1); } if (!webpagesToReload.isEmpty()) { - reloadWebPages(dialogId, webpagesToReload, scheduled); + reloadWebPages(dialogId, webpagesToReload, mode == 1); } }); } @@ -6029,9 +6192,7 @@ public class MessagesController extends BaseController implements NotificationCe SharedPreferences.Editor editor1 = null; if (preferences.contains("EnableGroup")) { boolean enabled = preferences.getBoolean("EnableGroup", true); - if (editor1 == null) { - editor1 = preferences.edit(); - } + editor1 = preferences.edit(); if (!enabled) { editor1.putInt("EnableGroup2", Integer.MAX_VALUE); editor1.putInt("EnableChannel2", Integer.MAX_VALUE); @@ -6059,7 +6220,7 @@ public class MessagesController extends BaseController implements NotificationCe req.peer = new TLRPC.TL_inputNotifyChats(); } else if (a == 1) { req.peer = new TLRPC.TL_inputNotifyUsers(); - } else if (a == 2) { + } else { req.peer = new TLRPC.TL_inputNotifyBroadcasts(); } final int type = a; @@ -6096,7 +6257,7 @@ public class MessagesController extends BaseController implements NotificationCe if ((notify_settings.flags & 4) != 0) { editor.putInt("EnableAll2", notify_settings.mute_until); } - } else if (type == 2) { + } else { if ((notify_settings.flags & 1) != 0) { editor.putBoolean("EnablePreviewChannel", notify_settings.show_previews); } @@ -6426,7 +6587,9 @@ public class MessagesController extends BaseController implements NotificationCe MessageObject messageObject = dialogMessage.get(oldDialog.id); dialogMessage.remove(oldDialog.id); if (messageObject != null) { - dialogMessagesByIds.remove(messageObject.getId()); + if (messageObject.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(messageObject.getId()); + } if (messageObject.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(messageObject.messageOwner.random_id); } @@ -6557,11 +6720,10 @@ public class MessagesController extends BaseController implements NotificationCe long did = cursor.longValue(0); int folder_id = cursor.intValue(1); TLRPC.Dialog dialog = dialogHashMap.get(did); - if (dialog.folder_id != folder_id) { - continue; - } - dialogHashMap.remove(did); if (dialog != null) { + if (dialog.folder_id != folder_id) { + continue; + } dialogsRes.dialogs.remove(dialog); for (int a = 0; a < dialogsRes.messages.size(); a++) { TLRPC.Message message = dialogsRes.messages.get(a); @@ -6576,6 +6738,7 @@ public class MessagesController extends BaseController implements NotificationCe } } } + dialogHashMap.remove(did); } cursor.dispose(); if (BuildVars.LOGS_ENABLED) { @@ -6852,7 +7015,7 @@ public class MessagesController extends BaseController implements NotificationCe if (!chat.megagroup) { allowCheck = false; } - if (chat.left && (promoDialogId == 0 || promoDialogId != d.id)) { + if (ChatObject.isNotInChat(chat) && (promoDialogId == 0 || promoDialogId != d.id)) { continue; } } @@ -6962,15 +7125,15 @@ public class MessagesController extends BaseController implements NotificationCe if (value.folder_id != folderId) { archivedDialogsCount++; } + MessageObject newMsg = new_dialogMessage.get(value.id); if (currentDialog == null) { added = true; dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject != null && messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - if (messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); + dialogMessage.put(key, newMsg); + if (newMsg != null && newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); } } } else { @@ -6983,33 +7146,42 @@ public class MessagesController extends BaseController implements NotificationCe if (oldMsg != null && oldMsg.deleted || oldMsg == null || currentDialog.top_message > 0) { if (value.top_message >= currentDialog.top_message) { dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject != null && messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - if (messageObject != null && messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); - } - } + dialogMessage.put(key, newMsg); if (oldMsg != null) { - dialogMessagesByIds.remove(oldMsg.getId()); + if (oldMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(oldMsg.getId()); + } if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } } - } - } else { - MessageObject newMsg = new_dialogMessage.get(value.id); - if (oldMsg.deleted || newMsg == null && (oldMsg == null || oldMsg.isSent()) || newMsg != null && newMsg.messageOwner.date > oldMsg.messageOwner.date) { - dialogs_dict.put(key, value); - dialogMessage.put(key, newMsg); - if (newMsg != null && newMsg.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(newMsg.getId(), newMsg); - if (newMsg != null && newMsg.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + if (newMsg != null) { + if (oldMsg != null && oldMsg.getId() == newMsg.getId()) { + newMsg.deleted = oldMsg.deleted; + } + if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } + } + } + } + } else { + if (newMsg == null && oldMsg.isSent() || newMsg != null && newMsg.messageOwner.date > oldMsg.messageOwner.date) { + dialogs_dict.put(key, value); + dialogMessage.put(key, newMsg); + if (oldMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(oldMsg.getId()); + } + if (newMsg != null) { + if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } } } - dialogMessagesByIds.remove(oldMsg.getId()); if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } @@ -7303,6 +7475,9 @@ public class MessagesController extends BaseController implements NotificationCe } req.limit = 1; checkingLastMessagesDialogs.put(lower_id, true); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("checkLastDialogMessage for " + lower_id); + } final long newTaskId; if (taskId == 0) { @@ -7337,6 +7512,9 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; removeDeletedMessagesFromArray(lower_id, res.messages); if (!res.messages.isEmpty()) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("checkLastDialogMessage for " + lower_id + " has message"); + } TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); TLRPC.Message newMessage = res.messages.get(0); TLRPC.Dialog newDialog = new TLRPC.TL_dialog(); @@ -7359,16 +7537,27 @@ public class MessagesController extends BaseController implements NotificationCe dialogs.dialogs.add(newDialog); dialogs.messages.addAll(res.messages); dialogs.count = 1; - processDialogsUpdate(dialogs, null); + processDialogsUpdate(dialogs, null, false); getMessagesStorage().putMessages(res.messages, true, true, false, getDownloadController().getAutodownloadMask(), true, false); } else { AndroidUtilities.runOnUIThread(() -> { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("checkLastDialogMessage for " + lower_id + " has not message"); + } if (getMediaDataController().getDraft(dialog.id, 0) == null) { TLRPC.Dialog currentDialog = dialogs_dict.get(dialog.id); if (currentDialog == null) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("checkLastDialogMessage for " + lower_id + " current dialog not found"); + } getMessagesStorage().isDialogHasTopMessage(dialog.id, () -> deleteDialog(dialog.id, 3)); - } else if (currentDialog.top_message == 0) { - deleteDialog(dialog.id, 3); + } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("checkLastDialogMessage for " + lower_id + " current dialog top message " + currentDialog.top_message); + } + if (currentDialog.top_message == 0) { + deleteDialog(dialog.id, 3); + } } } }); @@ -7381,7 +7570,7 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayList encChats) { + public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayList encChats, boolean fromCache) { Utilities.stageQueue.postRunnable(() -> { final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); final LongSparseArray new_dialogMessage = new LongSparseArray<>(); @@ -7403,7 +7592,7 @@ public class MessagesController extends BaseController implements NotificationCe if (promoDialogId == 0 || promoDialogId != message.dialog_id) { if (message.peer_id.channel_id != 0) { TLRPC.Chat chat = chatsDict.get(message.peer_id.channel_id); - if (chat != null && chat.left) { + if (chat != null && ChatObject.isNotInChat(chat)) { continue; } } else if (message.peer_id.chat_id != 0) { @@ -7422,7 +7611,7 @@ public class MessagesController extends BaseController implements NotificationCe if (promoDialogId == 0 || promoDialogId != d.id) { if (DialogObject.isChannel(d)) { TLRPC.Chat chat = chatsDict.get(-(int) d.id); - if (chat != null && chat.left) { + if (chat != null && ChatObject.isNotInChat(chat)) { continue; } } else if ((int) d.id < 0) { @@ -7460,24 +7649,41 @@ public class MessagesController extends BaseController implements NotificationCe for (int a = 0; a < new_dialogs_dict.size(); a++) { long key = new_dialogs_dict.keyAt(a); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate " + key); + } TLRPC.Dialog value = new_dialogs_dict.valueAt(a); TLRPC.Dialog currentDialog = dialogs_dict.get(key); + MessageObject newMsg = new_dialogMessage.get(value.id); if (currentDialog == null) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate dialog null"); + } int offset = nextDialogsCacheOffset.get(value.folder_id, 0) + 1; nextDialogsCacheOffset.put(value.folder_id, offset); dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject == null) { - checkLastDialogMessage(value, null, 0); - } else if (messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, messageObject.messageOwner.date); - if (messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); + dialogMessage.put(key, newMsg); + if (newMsg == null) { + if (fromCache) { + checkLastDialogMessage(value, null, 0); + } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate new message is null"); + } + } else if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, newMsg.messageOwner.date); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate new message not null"); } } } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate dialog not null"); + } currentDialog.unread_count = value.unread_count; if (currentDialog.unread_mentions_count != value.unread_mentions_count) { currentDialog.unread_mentions_count = value.unread_mentions_count; @@ -7486,41 +7692,58 @@ public class MessagesController extends BaseController implements NotificationCe } } MessageObject oldMsg = dialogMessage.get(key); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate oldMsg " + oldMsg + " old top_message = " + currentDialog.top_message + " new top_message = " + value.top_message); + FileLog.d("processDialogsUpdate oldMsgDeleted " + (oldMsg != null && oldMsg.deleted)); + } if (oldMsg == null || currentDialog.top_message > 0) { if (oldMsg != null && oldMsg.deleted || value.top_message > currentDialog.top_message) { dialogs_dict.put(key, value); - MessageObject messageObject = new_dialogMessage.get(value.id); - dialogMessage.put(key, messageObject); - if (messageObject != null && messageObject.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(messageObject.getId(), messageObject); - dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, messageObject.messageOwner.date); - if (messageObject.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(messageObject.messageOwner.random_id, messageObject); - } - } - if (oldMsg != null) { + dialogMessage.put(key, newMsg); + if (oldMsg != null && oldMsg.messageOwner.peer_id.channel_id == 0) { dialogMessagesByIds.remove(oldMsg.getId()); if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } } - if (messageObject == null) { - checkLastDialogMessage(value, null, 0); + if (newMsg != null) { + if (oldMsg != null && oldMsg.getId() == newMsg.getId()) { + newMsg.deleted = oldMsg.deleted; + } + if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, newMsg.messageOwner.date); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } + } + } + } + if (fromCache && newMsg == null) { + checkLastDialogMessage(value, null, 0); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("processDialogsUpdate new message is null"); } } } else { - MessageObject newMsg = new_dialogMessage.get(value.id); if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) { dialogs_dict.put(key, value); dialogMessage.put(key, newMsg); - if (newMsg != null && newMsg.messageOwner.peer_id.channel_id == 0) { - dialogMessagesByIds.put(newMsg.getId(), newMsg); - dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, newMsg.messageOwner.date); - if (newMsg.messageOwner.random_id != 0) { - dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + if (oldMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(oldMsg.getId()); + } + if (newMsg != null) { + if (oldMsg.getId() == newMsg.getId()) { + newMsg.deleted = oldMsg.deleted; + } + if (newMsg.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.put(newMsg.getId(), newMsg); + dialogsLoadedTillDate = Math.min(dialogsLoadedTillDate, newMsg.messageOwner.date); + if (newMsg.messageOwner.random_id != 0) { + dialogMessagesByRandomIds.put(newMsg.messageOwner.random_id, newMsg); + } } } - dialogMessagesByIds.remove(oldMsg.getId()); if (oldMsg.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(oldMsg.messageOwner.random_id); } @@ -8184,7 +8407,7 @@ public class MessagesController extends BaseController implements NotificationCe AndroidUtilities.runOnUIThread(() -> { info.about = about; getMessagesStorage().updateChatInfo(info, false); - getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false, null); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false); }); } }, ConnectionsManager.RequestFlagInvokeAfter); @@ -8340,7 +8563,7 @@ public class MessagesController extends BaseController implements NotificationCe newPart.date = getConnectionsManager().getCurrentTime(); info.participants.participants.add(0, newPart); getMessagesStorage().updateChatInfo(info, true); - getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false, null); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false); getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT_MEMBERS); } } @@ -8427,7 +8650,7 @@ public class MessagesController extends BaseController implements NotificationCe } if (changed) { getMessagesStorage().updateChatInfo(info, true); - getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false, null); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false); } getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT_MEMBERS); } @@ -9010,7 +9233,7 @@ public class MessagesController extends BaseController implements NotificationCe } inputChannel = getInputChannel(chat); } - if (inputChannel == null || inputChannel.access_hash == 0) { + if (inputChannel.access_hash == 0) { if (taskId != 0) { getMessagesStorage().removePendingTask(taskId); } @@ -9540,15 +9763,11 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.TL_dialogPeer dialogPeer = (TLRPC.TL_dialogPeer) peer; long did; if (dialogPeer.peer.user_id != 0) { - if (dialogPeer.peer.user_id != 0) { - did = dialogPeer.peer.user_id; - } else if (dialogPeer.peer.chat_id != 0) { - did = -dialogPeer.peer.chat_id; - } else { - did = -dialogPeer.peer.channel_id; - } + did = dialogPeer.peer.user_id; + } else if (dialogPeer.peer.chat_id != 0) { + did = -dialogPeer.peer.chat_id; } else { - did = 0; + did = -dialogPeer.peer.channel_id; } getMessagesStorage().setDialogUnread(did, true); TLRPC.Dialog dialog = dialogs_dict.get(did); @@ -10011,7 +10230,7 @@ public class MessagesController extends BaseController implements NotificationCe } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { return 1; } else if (update instanceof TLRPC.TL_updateNewChannelMessage || update instanceof TLRPC.TL_updateDeleteChannelMessages || update instanceof TLRPC.TL_updateEditChannelMessage || - update instanceof TLRPC.TL_updateChannelWebPage) { + update instanceof TLRPC.TL_updateChannelWebPage || update instanceof TLRPC.TL_updatePinnedChannelMessages) { return 2; } else { return 3; @@ -10045,6 +10264,10 @@ public class MessagesController extends BaseController implements NotificationCe return ((TLRPC.TL_updateChannelTooLong) update).pts; } else if (update instanceof TLRPC.TL_updateFolderPeers) { return ((TLRPC.TL_updateFolderPeers) update).pts; + } else if (update instanceof TLRPC.TL_updatePinnedChannelMessages) { + return ((TLRPC.TL_updatePinnedChannelMessages) update).pts; + } else if (update instanceof TLRPC.TL_updatePinnedMessages) { + return ((TLRPC.TL_updatePinnedMessages) update).pts; } else { return 0; } @@ -10075,6 +10298,10 @@ public class MessagesController extends BaseController implements NotificationCe return ((TLRPC.TL_updateReadMessagesContents) update).pts_count; } else if (update instanceof TLRPC.TL_updateFolderPeers) { return ((TLRPC.TL_updateFolderPeers) update).pts_count; + } else if (update instanceof TLRPC.TL_updatePinnedChannelMessages) { + return ((TLRPC.TL_updatePinnedChannelMessages) update).pts_count; + } else if (update instanceof TLRPC.TL_updatePinnedMessages) { + return ((TLRPC.TL_updatePinnedMessages) update).pts_count; } else { return 0; } @@ -10101,8 +10328,6 @@ public class MessagesController extends BaseController implements NotificationCe return ((TLRPC.TL_updateChannelMessageForwards) update).channel_id; } else if (update instanceof TLRPC.TL_updateChannelTooLong) { return ((TLRPC.TL_updateChannelTooLong) update).channel_id; - } else if (update instanceof TLRPC.TL_updateChannelPinnedMessage) { - return ((TLRPC.TL_updateChannelPinnedMessage) update).channel_id; } else if (update instanceof TLRPC.TL_updateChannelReadMessagesContents) { return ((TLRPC.TL_updateChannelReadMessagesContents) update).channel_id; } else if (update instanceof TLRPC.TL_updateChannelAvailableMessages) { @@ -10121,6 +10346,8 @@ public class MessagesController extends BaseController implements NotificationCe return ((TLRPC.TL_updateReadChannelDiscussionOutbox) update).channel_id; } else if (update instanceof TLRPC.TL_updateChannelUserTyping) { return ((TLRPC.TL_updateChannelUserTyping) update).channel_id; + } else if (update instanceof TLRPC.TL_updatePinnedChannelMessages) { + return ((TLRPC.TL_updatePinnedChannelMessages) update).channel_id; } else { if (BuildVars.LOGS_ENABLED) { FileLog.e("trying to get unknown update channel_id for " + update); @@ -10415,7 +10642,7 @@ public class MessagesController extends BaseController implements NotificationCe if (BuildVars.LOGS_ENABLED) { FileLog.d(update + " need get diff, pts: " + getMessagesStorage().getLastPtsValue() + " " + updatesNew.pts + " count = " + updatesNew.pts_count); } - if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && Math.abs(System.currentTimeMillis() - updatesStartWaitTimePts) <= 1500) { + if (gettingDifference || updatesStartWaitTimePts == 0 || Math.abs(System.currentTimeMillis() - updatesStartWaitTimePts) <= 1500) { if (updatesStartWaitTimePts == 0) { updatesStartWaitTimePts = System.currentTimeMillis(); } @@ -10451,7 +10678,7 @@ public class MessagesController extends BaseController implements NotificationCe if (BuildVars.LOGS_ENABLED) { FileLog.d(update + " need get diff, qts: " + getMessagesStorage().getLastQtsValue() + " " + updatesNew.pts); } - if (gettingDifference || updatesStartWaitTimeQts == 0 || updatesStartWaitTimeQts != 0 && Math.abs(System.currentTimeMillis() - updatesStartWaitTimeQts) <= 1500) { + if (gettingDifference || updatesStartWaitTimeQts == 0 || Math.abs(System.currentTimeMillis() - updatesStartWaitTimeQts) <= 1500) { if (updatesStartWaitTimeQts == 0) { updatesStartWaitTimeQts = System.currentTimeMillis(); } @@ -10845,7 +11072,7 @@ public class MessagesController extends BaseController implements NotificationCe ImageLoader.saveMessageThumbs(message); MessageObject.getDialogId(message); - if (baseUpdate instanceof TLRPC.TL_updateNewChannelMessage && message.reply_to != null) { + if (baseUpdate instanceof TLRPC.TL_updateNewChannelMessage && message.reply_to != null && !(message.action instanceof TLRPC.TL_messageActionPinMessage)) { if (channelReplies == null) { channelReplies = new SparseArray<>(); } @@ -10988,6 +11215,11 @@ public class MessagesController extends BaseController implements NotificationCe } else { markAsReadMessagesOutbox.put(update.peer.user_id, update.max_id); dialog_id = update.peer.user_id; + TLRPC.User user = getUser(update.peer.user_id); + if (user != null && user.status != null && user.status.expires <= 0 && Math.abs(getConnectionsManager().getCurrentTime() - date) < 30) { + onlinePrivacy.put(update.peer.user_id, date); + interfaceUpdateMask |= UPDATE_MASK_STATUS; + } } Integer value = dialogs_read_outbox_max.get(dialog_id); if (value == null) { @@ -11594,18 +11826,15 @@ public class MessagesController extends BaseController implements NotificationCe array.put(message.dialog_id, arr); } arr.add(obj); - } else if (baseUpdate instanceof TLRPC.TL_updateChannelPinnedMessage) { - TLRPC.TL_updateChannelPinnedMessage update = (TLRPC.TL_updateChannelPinnedMessage) baseUpdate; + } else if (baseUpdate instanceof TLRPC.TL_updatePinnedChannelMessages) { + TLRPC.TL_updatePinnedChannelMessages update = (TLRPC.TL_updatePinnedChannelMessages) baseUpdate; if (BuildVars.LOGS_ENABLED) { FileLog.d(baseUpdate + " channelId = " + update.channel_id); } - getMessagesStorage().updateChatPinnedMessage(update.channel_id, update.id); - } else if (baseUpdate instanceof TLRPC.TL_updateChatPinnedMessage) { - TLRPC.TL_updateChatPinnedMessage update = (TLRPC.TL_updateChatPinnedMessage) baseUpdate; - getMessagesStorage().updateChatPinnedMessage(update.chat_id, update.id); - } else if (baseUpdate instanceof TLRPC.TL_updateUserPinnedMessage) { - TLRPC.TL_updateUserPinnedMessage update = (TLRPC.TL_updateUserPinnedMessage) baseUpdate; - getMessagesStorage().updateUserPinnedMessage(update.user_id, update.id); + getMessagesStorage().updatePinnedMessages(-update.channel_id, update.messages, update.pinned, -1, 0, false, null); + } else if (baseUpdate instanceof TLRPC.TL_updatePinnedMessages) { + TLRPC.TL_updatePinnedMessages update = (TLRPC.TL_updatePinnedMessages) baseUpdate; + getMessagesStorage().updatePinnedMessages(MessageObject.getPeerId(update.peer), update.messages, update.pinned, -1, 0, false, null); } else if (baseUpdate instanceof TLRPC.TL_updateReadFeaturedStickers) { if (updatesOnMainThread == null) { updatesOnMainThread = new ArrayList<>(); @@ -12467,6 +12696,9 @@ public class MessagesController extends BaseController implements NotificationCe Integer id = arrayList.get(b); MessageObject obj = dialogMessagesByIds.get(id); if (obj != null) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("mark messages " + obj.getId() + " deleted"); + } obj.deleted = true; } } @@ -12590,7 +12822,13 @@ public class MessagesController extends BaseController implements NotificationCe return false; } - public CharSequence getPrintingString(long dialogId, int threadId) { + public CharSequence getPrintingString(long dialogId, int threadId, boolean isDialog) { + if (isDialog && (int) dialogId > 0) { + TLRPC.User user = getUser((int) dialogId); + if (user != null && user.status != null && user.status.expires < 0) { + return null; + } + } SparseArray threads = printingStrings.get(dialogId); if (threads == null) { return null; @@ -12736,7 +12974,9 @@ public class MessagesController extends BaseController implements NotificationCe dialogs.remove(dialog); } MessageObject object = dialogMessagesByIds.get(dialog.top_message); - dialogMessagesByIds.remove(dialog.top_message); + if (object != null && object.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(dialog.top_message); + } if (object != null && object.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(object.messageOwner.random_id); } @@ -12751,7 +12991,7 @@ public class MessagesController extends BaseController implements NotificationCe if (dialog == null) { TLRPC.Chat chat = getChat(channelId); - if (channelId != 0 && chat == null || chat != null && ChatObject.isNotInChat(chat)) { + if (channelId != 0 && chat == null || chat != null && (ChatObject.isNotInChat(chat) || chat.min)) { return false; } if (BuildVars.LOGS_ENABLED) { @@ -12793,7 +13033,9 @@ public class MessagesController extends BaseController implements NotificationCe (dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) || dialogMessage.indexOfKey(uid) < 0 || dialog.top_message < 0 || dialog.last_message_date <= lastMessage.messageOwner.date) { MessageObject object = dialogMessagesByIds.get(dialog.top_message); - dialogMessagesByIds.remove(dialog.top_message); + if (object != null && object.messageOwner.peer_id.channel_id == 0) { + dialogMessagesByIds.remove(dialog.top_message); + } if (object != null && object.messageOwner.random_id != 0) { dialogMessagesByRandomIds.remove(object.messageOwner.random_id); } @@ -12951,7 +13193,7 @@ public class MessagesController extends BaseController implements NotificationCe } dialogsCanAddUsers.add(d); dialogsGroupsOnly.add(d); - } else if (lower_id > 0 && lower_id != selfId) { + } else if (lower_id != selfId) { dialogsUsersOnly.add(d); if (!UserObject.isReplyUser(lower_id)) { dialogsForBlock.add(d); @@ -13075,7 +13317,7 @@ public class MessagesController extends BaseController implements NotificationCe String reason = null; if (chat != null) { reason = getRestrictionReason(chat.restriction_reason); - } else if (user != null) { + } else { reason = getRestrictionReason(user.restriction_reason); } if (reason != null) { @@ -13119,9 +13361,7 @@ public class MessagesController extends BaseController implements NotificationCe }); progressDialog.setOnCancelListener(dialog -> { getConnectionsManager().cancelRequest(reqId, true); - if (fragment != null) { - fragment.setVisibleDialog(null); - } + fragment.setVisibleDialog(null); }); fragment.setVisibleDialog(progressDialog); progressDialog.show(); @@ -13138,7 +13378,7 @@ public class MessagesController extends BaseController implements NotificationCe String reason = null; if (chat != null) { reason = getRestrictionReason(chat.restriction_reason); - } else if (user != null) { + } else { reason = getRestrictionReason(user.restriction_reason); if (type != 3 && user.bot) { type = 1; @@ -13213,7 +13453,7 @@ public class MessagesController extends BaseController implements NotificationCe openChatOrProfileWith(res.users.get(0), null, fragment, type, false); } } else { - if (fragment != null && fragment.getParentActivity() != null) { + if (fragment.getParentActivity() != null) { try { Toast.makeText(fragment.getParentActivity(), LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound), Toast.LENGTH_SHORT).show(); } catch (Exception e) { @@ -13254,7 +13494,7 @@ public class MessagesController extends BaseController implements NotificationCe ArrayList messArr = (ArrayList) args[2]; boolean isCache = (Boolean) args[3]; if (messArr.isEmpty() && isCache) { - loadMessages(dialog_id, 0, false, 20, 3, 0, false, 0, classGuid, 3, 0, false, false, 0, 0, 0); + loadMessages(dialog_id, 0, false, 20, 3, 0, false, 0, classGuid, 3, 0, false, 0, 0, 0, 0); } else { getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.loadingMessagesFailed); @@ -13275,6 +13515,6 @@ public class MessagesController extends BaseController implements NotificationCe getNotificationCenter().addObserver(delegate, NotificationCenter.loadingMessagesFailed); } - loadMessages(dialog_id, 0, false, 1, finalMessageId, 0, true, 0, classGuid, 3, 0, false, false, 0, 0, 0); + loadMessages(dialog_id, 0, false, 1, finalMessageId, 0, true, 0, classGuid, 3, 0, false, 0, 0, 0, 0); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index a276c3ce2..23806535e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -86,7 +86,7 @@ public class MessagesStorage extends BaseController { private CountDownLatch openSync = new CountDownLatch(1); private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT]; - private final static int LAST_DB_VERSION = 70; + private final static int LAST_DB_VERSION = 73; public static MessagesStorage getInstance(int num) { MessagesStorage localInstance = Instance[num]; @@ -337,8 +337,8 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE user_settings(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS user_settings_pinned_idx ON user_settings(uid, pinned) WHERE pinned != 0;").stepThis().dispose(); - database.executeFast("CREATE TABLE chat_pinned(uid INTEGER PRIMARY KEY, pinned INTEGER, data BLOB)").stepThis().dispose(); - database.executeFast("CREATE INDEX IF NOT EXISTS chat_pinned_mid_idx ON chat_pinned(uid, pinned) WHERE pinned != 0;").stepThis().dispose(); + database.executeFast("CREATE TABLE chat_pinned_v2(uid INTEGER, mid INTEGER, data BLOB, PRIMARY KEY (uid, mid));").stepThis().dispose(); + database.executeFast("CREATE TABLE chat_pinned_count(uid INTEGER PRIMARY KEY, count INTEGER, end INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE chat_hints(did INTEGER, type INTEGER, rating REAL, date INTEGER, PRIMARY KEY(did, type))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS chat_hints_rating_idx ON chat_hints(rating);").stepThis().dispose(); @@ -368,7 +368,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE bot_info(uid INTEGER PRIMARY KEY, info BLOB)").stepThis().dispose(); database.executeFast("CREATE TABLE pending_tasks(id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); database.executeFast("CREATE TABLE requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end));").stepThis().dispose(); - database.executeFast("CREATE TABLE sharing_locations(uid INTEGER PRIMARY KEY, mid INTEGER, date INTEGER, period INTEGER, message BLOB);").stepThis().dispose(); + database.executeFast("CREATE TABLE sharing_locations(uid INTEGER PRIMARY KEY, mid INTEGER, date INTEGER, period INTEGER, message BLOB, proximity INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE emoji_keywords_v2(lang TEXT, keyword TEXT, emoji TEXT, PRIMARY KEY(lang, keyword, emoji));").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS emoji_keywords_v2_keyword ON emoji_keywords_v2(keyword);").stepThis().dispose(); @@ -386,9 +386,6 @@ public class MessagesStorage extends BaseController { //version database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose(); - - //database.executeFast("CREATE TABLE secret_holes(uid INTEGER, seq_in INTEGER, seq_out INTEGER, data BLOB, PRIMARY KEY (uid, seq_in, seq_out));").stepThis().dispose(); - //database.executeFast("CREATE TABLE attach_data(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); } else { int version = database.executeInt("PRAGMA user_version"); if (BuildVars.LOGS_ENABLED) { @@ -685,8 +682,6 @@ public class MessagesStorage extends BaseController { if (version == 30) { database.executeFast("ALTER TABLE chat_settings_v2 ADD COLUMN pinned INTEGER default 0").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS chat_settings_pinned_idx ON chat_settings_v2(uid, pinned) WHERE pinned != 0;").stepThis().dispose(); - database.executeFast("CREATE TABLE IF NOT EXISTS chat_pinned(uid INTEGER PRIMARY KEY, pinned INTEGER, data BLOB)").stepThis().dispose(); - database.executeFast("CREATE INDEX IF NOT EXISTS chat_pinned_mid_idx ON chat_pinned(uid, pinned) WHERE pinned != 0;").stepThis().dispose(); database.executeFast("CREATE TABLE IF NOT EXISTS users_data(uid INTEGER PRIMARY KEY, about TEXT)").stepThis().dispose(); database.executeFast("PRAGMA user_version = 31").stepThis().dispose(); version = 31; @@ -791,7 +786,6 @@ public class MessagesStorage extends BaseController { version = 49; } if (version == 49) { - database.executeFast("DELETE FROM chat_pinned WHERE uid = 1").stepThis().dispose(); database.executeFast("CREATE TABLE IF NOT EXISTS user_settings(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS user_settings_pinned_idx ON user_settings(uid, pinned) WHERE pinned != 0;").stepThis().dispose(); database.executeFast("PRAGMA user_version = 50").stepThis().dispose(); @@ -910,6 +904,21 @@ public class MessagesStorage extends BaseController { version = 70; } if (version == 70) { + database.executeFast("CREATE TABLE IF NOT EXISTS chat_pinned_v2(uid INTEGER, mid INTEGER, data BLOB, PRIMARY KEY (uid, mid));").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 71").stepThis().dispose(); + version = 71; + } + if (version == 71) { + database.executeFast("ALTER TABLE sharing_locations ADD COLUMN proximity INTEGER default 0").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 72").stepThis().dispose(); + version = 72; + } + if (version == 72) { + database.executeFast("CREATE TABLE IF NOT EXISTS chat_pinned_count(uid INTEGER PRIMARY KEY, count INTEGER, end INTEGER);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 73").stepThis().dispose(); + version = 73; + } + if (version == 73) { } } catch (Exception e) { @@ -2905,6 +2914,7 @@ public class MessagesStorage extends BaseController { final ArrayList mids = new ArrayList<>(); SQLiteCursor cursor = database.queryFinalized("SELECT data FROM messages WHERE uid = " + did); ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); try { while (cursor.next()) { @@ -2915,7 +2925,7 @@ public class MessagesStorage extends BaseController { message.readAttachPath(data, getUserConfig().clientUserId); if (UserObject.isReplyUser(did) && MessageObject.getPeerId(message.fwd_from.from_id) == fromId || MessageObject.getFromChatId(message) == fromId && message.id != 1) { mids.add(message.id); - addFilesToDelete(message, filesToDelete, idsToDelete, false); + addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false); } } data.reuse(); @@ -2926,7 +2936,10 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); - AndroidUtilities.runOnUIThread(() -> getMessagesController().markDialogMessageAsDeleted(mids, did)); + AndroidUtilities.runOnUIThread(() -> { + getFileLoader().cancelLoadFiles(namesToDelete); + getMessagesController().markDialogMessageAsDeleted(mids, did); + }); markMessagesAsDeletedInternal(mids, channelId, false, false); updateDialogsWithDeletedMessagesInternal(mids, null, channelId); getFileLoader().deleteFiles(filesToDelete, 0); @@ -2939,7 +2952,7 @@ public class MessagesStorage extends BaseController { }); } - private boolean addFilesToDelete(TLRPC.Message message, ArrayList filesToDelete, ArrayList> ids, boolean forceCache) { + private boolean addFilesToDelete(TLRPC.Message message, ArrayList filesToDelete, ArrayList> ids, ArrayList namesToDelete, boolean forceCache) { if (message == null) { return false; } @@ -2972,21 +2985,29 @@ public class MessagesStorage extends BaseController { if (photo != null) { for (int a = 0, N = photo.sizes.size(); a < N; a++) { TLRPC.PhotoSize photoSize = photo.sizes.get(a); + String name = FileLoader.getAttachFileName(photoSize); + if (!TextUtils.isEmpty(name)) { + namesToDelete.add(name); + } File file = FileLoader.getPathToAttach(photoSize); - if (file != null && file.toString().length() > 0) { + if (file.toString().length() > 0) { filesToDelete.add(file); } } return true; } else if (document != null) { + String name = FileLoader.getAttachFileName(document); + if (!TextUtils.isEmpty(name)) { + namesToDelete.add(name); + } File file = FileLoader.getPathToAttach(document, forceCache); - if (file != null && file.toString().length() > 0) { + if (file.toString().length() > 0) { filesToDelete.add(file); } for (int a = 0, N = document.thumbs.size(); a < N; a++) { TLRPC.PhotoSize photoSize = document.thumbs.get(a); file = FileLoader.getPathToAttach(photoSize); - if (file != null && file.toString().length() > 0) { + if (file.toString().length() > 0) { filesToDelete.add(file); } } @@ -3012,6 +3033,7 @@ public class MessagesStorage extends BaseController { if ((int) did == 0 || messagesOnly == 2) { SQLiteCursor cursor = database.queryFinalized("SELECT data FROM messages WHERE uid = " + did); ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); try { while (cursor.next()) { @@ -3020,7 +3042,7 @@ public class MessagesStorage extends BaseController { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); - addFilesToDelete(message, filesToDelete, idsToDelete, false); + addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false); } } } catch (Exception e) { @@ -3028,13 +3050,15 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); + AndroidUtilities.runOnUIThread(() -> getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, messagesOnly); } if (messagesOnly == 0 || messagesOnly == 3) { database.executeFast("DELETE FROM dialogs WHERE did = " + did).stepThis().dispose(); database.executeFast("DELETE FROM chat_settings_v2 WHERE uid = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM chat_pinned WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM chat_pinned_v2 WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM chat_pinned_count WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM channel_users_v2 WHERE did = " + did).stepThis().dispose(); database.executeFast("DELETE FROM search_recent WHERE did = " + did).stepThis().dispose(); int lower_id = (int) did; @@ -3221,6 +3245,8 @@ public class MessagesStorage extends BaseController { String ids = "(" + TextUtils.join(",", dids) + ")"; database.beginTransaction(); + database.executeFast("DELETE FROM chat_pinned_count WHERE uid IN " + ids).stepThis().dispose(); + database.executeFast("DELETE FROM chat_pinned_v2 WHERE uid IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM dialogs WHERE did IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM messages WHERE uid IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM polls WHERE 1").stepThis().dispose(); @@ -3364,6 +3390,7 @@ public class MessagesStorage extends BaseController { storageQueue.postRunnable(() -> { try { ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); final ArrayList messages = new ArrayList<>(); SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date, uid FROM messages WHERE mid IN (%s)", TextUtils.join(",", mids))); @@ -3374,7 +3401,7 @@ public class MessagesStorage extends BaseController { message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); if (message.media != null) { - if (!addFilesToDelete(message, filesToDelete, idsToDelete, true)) { + if (!addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, true)) { continue; } else { if (message.media.document != null) { @@ -3451,6 +3478,7 @@ public class MessagesStorage extends BaseController { } }); } + AndroidUtilities.runOnUIThread(() -> getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, 0); } catch (Exception e) { FileLog.e(e); @@ -4267,7 +4295,7 @@ public class MessagesStorage extends BaseController { continue; } } - if (mutedDialogs.indexOfKey(did) >= 0 && filter.alwaysShow.indexOf(did) >= 0) { + if (mutedDialogs.indexOfKey(did) >= 0 && filter.alwaysShow.contains(did)) { unreadCount--; } } @@ -4574,7 +4602,7 @@ public class MessagesStorage extends BaseController { if (info instanceof TLRPC.TL_chatFull) { info.participants = participants; final TLRPC.ChatFull finalInfo = info; - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, finalInfo, 0, false, null)); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, finalInfo, 0, false)); SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_settings_v2 VALUES(?, ?, ?, ?)"); NativeByteBuffer data = new NativeByteBuffer(info.getObjectSize()); @@ -4631,10 +4659,10 @@ public class MessagesStorage extends BaseController { }); } - public void updateChannelUsers(final int channel_id, final ArrayList participants) { + public void updateChannelUsers(final int channelId, final ArrayList participants) { storageQueue.postRunnable(() -> { try { - long did = -channel_id; + long did = -channelId; database.executeFast("DELETE FROM channel_users_v2 WHERE did = " + did).stepThis().dispose(); database.beginTransaction(); SQLitePreparedStatement state = database.executeFast("REPLACE INTO channel_users_v2 VALUES(?, ?, ?, ?)"); @@ -4655,7 +4683,7 @@ public class MessagesStorage extends BaseController { } state.dispose(); database.commitTransaction(); - loadChatInfo(channel_id, null, false, true); + loadChatInfo(channelId, true, null, false, true); } catch (Exception e) { FileLog.e(e); } @@ -4724,12 +4752,16 @@ public class MessagesStorage extends BaseController { }); } - public void loadUserInfo(TLRPC.User user, final boolean force, int classGuid) { + public void loadUserInfo(TLRPC.User user, final boolean force, int classGuid, int fromMessageId) { if (user == null) { return; } storageQueue.postRunnable(() -> { - MessageObject pinnedMessageObject = null; + HashMap pinnedMessagesMap = new HashMap<>(); + ArrayList pinnedMessages = new ArrayList<>(); + int totalPinnedCount = 0; + boolean pinnedEndReached = false; + TLRPC.UserFull info = null; try { SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned FROM user_settings WHERE uid = " + user.id); @@ -4737,18 +4769,47 @@ public class MessagesStorage extends BaseController { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { info = TLRPC.UserFull.TLdeserialize(data, data.readInt32(false), false); - data.reuse(); info.pinned_msg_id = cursor.intValue(1); + data.reuse(); } } cursor.dispose(); + + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid FROM chat_pinned_v2 WHERE uid = %d ORDER BY mid DESC", user.id)); + while (cursor.next()) { + int id = cursor.intValue(0); + pinnedMessages.add(id); + pinnedMessagesMap.put(id, null); + } + cursor.dispose(); + + cursor = database.queryFinalized("SELECT count, end FROM chat_pinned_count WHERE uid = " + user.id); + if (cursor.next()) { + totalPinnedCount = cursor.intValue(0); + pinnedEndReached = cursor.intValue(1) != 0; + } + cursor.dispose(); + if (info != null && info.pinned_msg_id != 0) { - pinnedMessageObject = getMediaDataController().loadPinnedMessage(user.id, 0, info.pinned_msg_id, false); + if (pinnedMessages.isEmpty() || info.pinned_msg_id > pinnedMessages.get(0)) { + pinnedMessages.clear(); + pinnedMessages.add(info.pinned_msg_id); + pinnedMessagesMap.put(info.pinned_msg_id, null); + } + } + if (!pinnedMessages.isEmpty()) { + ArrayList messageObjects = getMediaDataController().loadPinnedMessages(user.id, 0, pinnedMessages, false); + if (messageObjects != null) { + for (int a = 0, N = messageObjects.size(); a < N; a++) { + MessageObject messageObject = messageObjects.get(a); + pinnedMessagesMap.put(messageObject.getId(), messageObject); + } + } } } catch (Exception e) { FileLog.e(e); } finally { - getMessagesController().processUserInfo(user, info, true, force, pinnedMessageObject, classGuid); + getMessagesController().processUserInfo(user, info, true, force, classGuid, pinnedMessages, pinnedMessagesMap, totalPinnedCount, pinnedEndReached); } }); } @@ -4847,43 +4908,6 @@ public class MessagesStorage extends BaseController { }); } - public void updateUserPinnedMessage(final int userId, final int messageId) { - storageQueue.postRunnable(() -> { - try { - SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned FROM user_settings WHERE uid = " + userId); - TLRPC.UserFull info = null; - if (cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - info = TLRPC.UserFull.TLdeserialize(data, data.readInt32(false), false); - data.reuse(); - info.pinned_msg_id = cursor.intValue(1); - } - } - cursor.dispose(); - if (info instanceof TLRPC.UserFull) { - info.pinned_msg_id = messageId; - info.flags |= 64; - - final TLRPC.UserFull finalInfo = info; - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, userId, finalInfo, null)); - - SQLitePreparedStatement state = database.executeFast("REPLACE INTO user_settings VALUES(?, ?, ?)"); - NativeByteBuffer data = new NativeByteBuffer(info.getObjectSize()); - info.serializeToStream(data); - state.bindInteger(1, userId); - state.bindByteBuffer(2, data); - state.bindInteger(3, info.pinned_msg_id); - state.step(); - state.dispose(); - data.reuse(); - } - } catch (Exception e) { - FileLog.e(e); - } - }); - } - public void updateChatOnlineCount(final int channelId, final int onlineCount) { storageQueue.postRunnable(() -> { try { @@ -4899,43 +4923,123 @@ public class MessagesStorage extends BaseController { }); } - public void updateChatPinnedMessage(final int channelId, final int messageId) { + public void updatePinnedMessages(long dialogId, ArrayList ids, boolean pin, int totalCount, int maxId, boolean end, HashMap messages) { storageQueue.postRunnable(() -> { try { - SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned, online FROM chat_settings_v2 WHERE uid = " + channelId); - TLRPC.ChatFull info = null; - if (cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - info = TLRPC.ChatFull.TLdeserialize(data, data.readInt32(false), false); - data.reuse(); - info.pinned_msg_id = cursor.intValue(1); - info.online_count = cursor.intValue(2); + if (pin) { + database.beginTransaction(); + int alreadyAdded = 0; + boolean endReached; + if (messages != null) { + if (maxId == 0) { + database.executeFast("DELETE FROM chat_pinned_v2 WHERE uid = " + dialogId).stepThis().dispose(); + } + } else { + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM chat_pinned_v2 WHERE uid = %d AND mid IN (%s)", dialogId, TextUtils.join(",", ids))); + alreadyAdded = cursor.next() ? cursor.intValue(0) : 0; } - } - cursor.dispose(); - if (info != null) { - if (info instanceof TLRPC.TL_channelFull) { - info.pinned_msg_id = messageId; - info.flags |= 32; - } else if (info instanceof TLRPC.TL_chatFull) { - info.pinned_msg_id = messageId; - info.flags |= 64; + SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_pinned_v2 VALUES(?, ?, ?)"); + for (int a = 0, N = ids.size(); a < N; a++) { + Integer id = ids.get(a); + state.requery(); + state.bindLong(1, dialogId); + state.bindInteger(2, id); + MessageObject message = null; + if (messages != null) { + message = messages.get(id); + } + NativeByteBuffer data = null; + if (message != null) { + data = new NativeByteBuffer(message.messageOwner.getObjectSize()); + message.messageOwner.serializeToStream(data); + state.bindByteBuffer(3, data); + } else { + state.bindNull(3); + } + state.step(); + if (data != null) { + data.reuse(); + } + } + state.dispose(); + database.commitTransaction(); + + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM chat_pinned_v2 WHERE uid = %d", dialogId)); + int newCount1 = cursor.next() ? cursor.intValue(0) : 0; + cursor.dispose(); + + int newCount; + if (messages != null) { + newCount = Math.max(totalCount, newCount1); + endReached = end; + } else { + SQLiteCursor cursor2 = database.queryFinalized(String.format(Locale.US, "SELECT count, end FROM chat_pinned_count WHERE uid = %d", dialogId)); + int newCount2; + if (cursor2.next()) { + newCount2 = cursor2.intValue(0); + endReached = cursor2.intValue(1) != 0; + } else { + newCount2 = 0; + endReached = false; + } + cursor2.dispose(); + newCount = Math.max(newCount2 + (ids.size() - alreadyAdded), newCount1); } - final TLRPC.ChatFull finalInfo = info; - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, finalInfo, 0, false, null)); - - SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_settings_v2 VALUES(?, ?, ?, ?)"); - NativeByteBuffer data = new NativeByteBuffer(info.getObjectSize()); - info.serializeToStream(data); - state.bindInteger(1, channelId); - state.bindByteBuffer(2, data); - state.bindInteger(3, info.pinned_msg_id); - state.bindInteger(4, info.online_count); + state = database.executeFast("REPLACE INTO chat_pinned_count VALUES(?, ?, ?)"); + state.requery(); + state.bindLong(1, dialogId); + state.bindInteger(2, newCount); + state.bindInteger(3, endReached ? 1 : 0); state.step(); state.dispose(); - data.reuse(); + + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialogId, ids, true, null, messages, maxId, newCount, endReached)); + } else { + int newCount; + boolean endReached; + if (ids == null) { + database.executeFast("DELETE FROM chat_pinned_v2 WHERE uid = " + dialogId).stepThis().dispose(); + if (dialogId < 0) { + database.executeFast("UPDATE chat_settings_v2 SET pinned = " + 0 + " WHERE uid = " + dialogId).stepThis().dispose(); + } else { + database.executeFast("UPDATE user_settings SET pinned = " + 0 + " WHERE uid = " + dialogId).stepThis().dispose(); + } + newCount = 0; + endReached = true; + } else { + database.executeFast(String.format("DELETE FROM chat_pinned_v2 WHERE uid = " + dialogId + " AND mid IN(%s)", TextUtils.join(",", ids))).stepThis().dispose(); + + SQLiteCursor cursor = database.queryFinalized("SELECT changes()"); + int updatedCount = cursor.next() ? cursor.intValue(0) : 0; + cursor.dispose(); + + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM chat_pinned_v2 WHERE uid = %d", dialogId)); + int newCount1 = cursor.next() ? cursor.intValue(0) : 0; + cursor.dispose(); + + cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, end FROM chat_pinned_count WHERE uid = %d", dialogId)); + int newCount2; + if (cursor.next()) { + newCount2 = Math.max(0, cursor.intValue(0) - updatedCount); + endReached = cursor.intValue(1) != 0; + } else { + newCount2 = 0; + endReached = false; + } + cursor.dispose(); + newCount = Math.max(newCount1, newCount2); + } + + SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_pinned_count VALUES(?, ?, ?)"); + state.requery(); + state.bindLong(1, dialogId); + state.bindInteger(2, newCount); + state.bindInteger(3, endReached ? 1 : 0); + state.step(); + state.dispose(); + + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialogId, ids, false, null, messages, maxId, newCount, endReached)); } } catch (Exception e) { FileLog.e(e); @@ -5000,7 +5104,7 @@ public class MessagesStorage extends BaseController { info.participants.version = version; final TLRPC.ChatFull finalInfo = info; - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, finalInfo, 0, false, null)); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, finalInfo, 0, false)); SQLitePreparedStatement state = database.executeFast("REPLACE INTO chat_settings_v2 VALUES(?, ?, ?, ?)"); NativeByteBuffer data = new NativeByteBuffer(info.getObjectSize()); @@ -5055,12 +5159,17 @@ public class MessagesStorage extends BaseController { return result[0]; } - private TLRPC.ChatFull loadChatInfoInternal(final int chat_id, final boolean force, final boolean byChannelUsers) { - MessageObject pinnedMessageObject = null; + private TLRPC.ChatFull loadChatInfoInternal(final int chatId, boolean isChannel, final boolean force, final boolean byChannelUsers, int fromMessageId) { TLRPC.ChatFull info = null; ArrayList loadedUsers = new ArrayList<>(); + + HashMap pinnedMessagesMap = new HashMap<>(); + ArrayList pinnedMessages = new ArrayList<>(); + int totalPinnedCount = 0; + boolean pinnedEndReached = false; + try { - SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned, online FROM chat_settings_v2 WHERE uid = " + chat_id); + SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned, online FROM chat_settings_v2 WHERE uid = " + chatId); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -5085,7 +5194,7 @@ public class MessagesStorage extends BaseController { getUsersInternal(usersToLoad.toString(), loadedUsers); } } else if (info instanceof TLRPC.TL_channelFull) { - cursor = database.queryFinalized("SELECT us.data, us.status, cu.data, cu.date FROM channel_users_v2 as cu LEFT JOIN users as us ON us.uid = cu.uid WHERE cu.did = " + (-chat_id) + " ORDER BY cu.date DESC"); + cursor = database.queryFinalized("SELECT us.data, us.status, cu.data, cu.date FROM channel_users_v2 as cu LEFT JOIN users as us ON us.uid = cu.uid WHERE cu.did = " + (-chatId) + " ORDER BY cu.date DESC"); info.participants = new TLRPC.TL_chatParticipants(); while (cursor.next()) { try { @@ -5131,21 +5240,54 @@ public class MessagesStorage extends BaseController { getUsersInternal(usersToLoad.toString(), loadedUsers); } } + + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid FROM chat_pinned_v2 WHERE uid = %d ORDER BY mid DESC", -chatId)); + while (cursor.next()) { + int id = cursor.intValue(0); + pinnedMessages.add(id); + pinnedMessagesMap.put(id, null); + } + cursor.dispose(); + + cursor = database.queryFinalized("SELECT count, end FROM chat_pinned_count WHERE uid = " + (-chatId)); + if (cursor.next()) { + totalPinnedCount = cursor.intValue(0); + pinnedEndReached = cursor.intValue(1) != 0; + } + cursor.dispose(); + if (info != null && info.pinned_msg_id != 0) { - pinnedMessageObject = getMediaDataController().loadPinnedMessage(-chat_id, info instanceof TLRPC.TL_channelFull ? chat_id : 0, info.pinned_msg_id, false); + if (pinnedMessages.isEmpty() || info.pinned_msg_id > pinnedMessages.get(0)) { + pinnedMessages.clear(); + pinnedMessages.add(info.pinned_msg_id); + pinnedMessagesMap.put(info.pinned_msg_id, null); + } + } + if (!pinnedMessages.isEmpty()) { + ArrayList messageObjects = getMediaDataController().loadPinnedMessages(-chatId, isChannel ? chatId : 0, pinnedMessages, false); + if (messageObjects != null) { + for (int a = 0, N = messageObjects.size(); a < N; a++) { + MessageObject messageObject = messageObjects.get(a); + pinnedMessagesMap.put(messageObject.getId(), messageObject); + } + } } } catch (Exception e) { FileLog.e(e); } finally { - getMessagesController().processChatInfo(chat_id, info, loadedUsers, true, force, byChannelUsers, pinnedMessageObject); + getMessagesController().processChatInfo(chatId, info, loadedUsers, true, force, byChannelUsers, pinnedMessages, pinnedMessagesMap, totalPinnedCount, pinnedEndReached); } return info; } - public TLRPC.ChatFull loadChatInfo(final int chat_id, final CountDownLatch countDownLatch, final boolean force, final boolean byChannelUsers) { + public TLRPC.ChatFull loadChatInfo(int chatId, boolean isChannel, CountDownLatch countDownLatch, boolean force, boolean byChannelUsers) { + return loadChatInfo(chatId, isChannel, countDownLatch, force, byChannelUsers, 0); + } + + public TLRPC.ChatFull loadChatInfo(int chatId, boolean isChannel, CountDownLatch countDownLatch, boolean force, boolean byChannelUsers, int fromMessageId) { TLRPC.ChatFull[] result = new TLRPC.ChatFull[1]; storageQueue.postRunnable(() -> { - result[0] = loadChatInfoInternal(chat_id, force, byChannelUsers); + result[0] = loadChatInfoInternal(chatId, isChannel, force, byChannelUsers, fromMessageId); if (countDownLatch != null) { countDownLatch.countDown(); } @@ -6515,7 +6657,7 @@ public class MessagesStorage extends BaseController { runnable.run(); }; } else {*/ - return () -> getMessagesController().processLoadedMessages(res, dialogId, mergeDialogId, countQueryFinal, maxIdOverrideFinal, offset_date, true, classGuid, minUnreadIdFinal, lastMessageIdFinal, countUnreadFinal, maxUnreadDateFinal, load_type, isChannel, isEndFinal, scheduled, replyMessageId, loadIndex, queryFromServerFinal, mentionsUnreadFinal); + return () -> getMessagesController().processLoadedMessages(res, dialogId, mergeDialogId, countQueryFinal, maxIdOverrideFinal, offset_date, true, classGuid, minUnreadIdFinal, lastMessageIdFinal, countUnreadFinal, maxUnreadDateFinal, load_type, isChannel, isEndFinal, scheduled ? 1 : 0, replyMessageId, loadIndex, queryFromServerFinal, mentionsUnreadFinal); //} } @@ -6523,14 +6665,14 @@ public class MessagesStorage extends BaseController { storageQueue.postRunnable(() -> { long mergeDialogIdFinal = mergeDialogId; int lowerId = (int) dialogId; - if (loadInfo) { + /*if (loadInfo) { if (lowerId < 0) { - TLRPC.ChatFull info = loadChatInfoInternal(-lowerId, true, false); + TLRPC.ChatFull info = loadChatInfoInternal(-lowerId, true, false, 0); if (info != null) { mergeDialogIdFinal = -info.migrated_from_chat_id; } } - } + }*/ Utilities.stageQueue.postRunnable(getMessagesInternal(dialogId, mergeDialogIdFinal, count, max_id, offset_date, minDate, classGuid, load_type, isChannel, scheduled, replyMessageId, loadIndex)); }); } @@ -7272,7 +7414,7 @@ public class MessagesStorage extends BaseController { Pair pair = ids.get(a); state.requery(); state.bindLong(1, pair.first); - state.bindInteger(1, pair.second); + state.bindInteger(2, pair.second); state.step(); } state.dispose(); @@ -7448,7 +7590,8 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); - + database.executeFast("DELETE FROM chat_pinned_count WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM chat_pinned_v2 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("UPDATE media_counts_v2 SET old = 1 WHERE uid = " + did).stepThis().dispose(); @@ -7638,9 +7781,7 @@ public class MessagesStorage extends BaseController { public void updateRepliesMaxReadId(int chatId, int mid, int readMaxId, boolean useQueue) { if (useQueue) { - storageQueue.postRunnable(() -> { - updateRepliesMaxReadIdInternal(chatId, mid, readMaxId); - }); + storageQueue.postRunnable(() -> updateRepliesMaxReadIdInternal(chatId, mid, readMaxId)); } else { updateRepliesMaxReadIdInternal(chatId, mid, readMaxId); } @@ -8748,6 +8889,7 @@ public class MessagesStorage extends BaseController { String ids; final ArrayList temp = new ArrayList<>(messages); LongSparseArray dialogsToUpdate = new LongSparseArray<>(); + LongSparseArray> messagesByDialogs = new LongSparseArray<>(); if (channelId != 0) { StringBuilder builder = new StringBuilder(messages.size()); for (int a = 0; a < messages.size(); a++) { @@ -8763,6 +8905,7 @@ public class MessagesStorage extends BaseController { ids = TextUtils.join(",", messages); } ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); int currentUser = getUserConfig().getClientUserId(); SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, data, read_state, out, mention, mid FROM messages WHERE mid IN(%s)", ids)); @@ -8772,6 +8915,12 @@ public class MessagesStorage extends BaseController { long did = cursor.longValue(0); int mid = cursor.intValue(5); temp.remove((Integer) mid); + ArrayList mids = messagesByDialogs.get(did); + if (mids == null) { + mids = new ArrayList<>(); + messagesByDialogs.put(did, mids); + } + mids.add(mid); if (did != currentUser) { int read_state = cursor.intValue(2); if (cursor.intValue(3) == 0) { @@ -8796,7 +8945,7 @@ public class MessagesStorage extends BaseController { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); - addFilesToDelete(message, filesToDelete, idsToDelete, false); + addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false); } } } catch (Exception e) { @@ -8804,6 +8953,7 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); + AndroidUtilities.runOnUIThread(() -> getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, 0); for (int a = 0; a < dialogsToUpdate.size(); a++) { @@ -8829,6 +8979,30 @@ public class MessagesStorage extends BaseController { state.dispose(); } + for (int a = 0, N = messagesByDialogs.size(); a < N; a++) { + long did = messagesByDialogs.keyAt(a); + ArrayList mids = messagesByDialogs.valueAt(a); + database.executeFast(String.format(Locale.US, "DELETE FROM chat_pinned_v2 WHERE uid = %d AND mid IN(%s)", did, TextUtils.join(",", mids))).stepThis().dispose(); + int updatedCount = 0; + cursor = database.queryFinalized("SELECT changes()"); + if (cursor.next()) { + updatedCount = cursor.intValue(0); + } + cursor.dispose(); + if (updatedCount > 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT count FROM chat_pinned_count WHERE uid = %d", did)); + if (cursor.next()) { + int count = cursor.intValue(0); + SQLitePreparedStatement state = database.executeFast("UPDATE chat_pinned_count SET count = ? WHERE uid = ?"); + state.requery(); + state.bindInteger(1, Math.max(0, count - updatedCount)); + state.bindLong(2, did); + state.step(); + state.dispose(); + } + cursor.dispose(); + } + } database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid IN(%s)", ids)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "DELETE FROM polls WHERE mid IN(%s)", ids)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "DELETE FROM bot_keyboard WHERE mid IN(%s)", ids)).stepThis().dispose(); @@ -8965,11 +9139,11 @@ public class MessagesStorage extends BaseController { NativeByteBuffer data = cursor.byteBufferValue(16); if (data != null) { dialogFolder.folder = TLRPC.TL_folder.TLdeserialize(data, data.readInt32(false), false); + data.reuse(); } else { dialogFolder.folder = new TLRPC.TL_folder(); dialogFolder.folder.id = cursor.intValue(15); } - data.reuse(); } dialog = dialogFolder; } else { @@ -9043,7 +9217,7 @@ public class MessagesStorage extends BaseController { } if (!dialogs.dialogs.isEmpty() || !encryptedChats.isEmpty()) { - getMessagesController().processDialogsUpdate(dialogs, encryptedChats); + getMessagesController().processDialogsUpdate(dialogs, encryptedChats, true); } } catch (Exception e) { FileLog.e(e); @@ -9082,6 +9256,7 @@ public class MessagesStorage extends BaseController { maxMessageId |= ((long) channelId) << 32; ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); int currentUser = getUserConfig().getClientUserId(); @@ -9114,7 +9289,7 @@ public class MessagesStorage extends BaseController { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); - addFilesToDelete(message, filesToDelete, idsToDelete, false); + addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false); } } } catch (Exception e) { @@ -9123,6 +9298,7 @@ public class MessagesStorage extends BaseController { cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); + AndroidUtilities.runOnUIThread(() -> getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, 0); for (int a = 0; a < dialogsToUpdate.size(); a++) { @@ -9148,6 +9324,27 @@ public class MessagesStorage extends BaseController { state.dispose(); } + database.executeFast(String.format(Locale.US, "DELETE FROM chat_pinned_v2 WHERE uid = %d AND mid <= %d", -channelId, maxMessageId)).stepThis().dispose(); + int updatedCount = 0; + cursor = database.queryFinalized("SELECT changes()"); + if (cursor.next()) { + updatedCount = cursor.intValue(0); + } + cursor.dispose(); + if (updatedCount > 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT count FROM chat_pinned_count WHERE uid = %d", -channelId)); + if (cursor.next()) { + int count = cursor.intValue(0); + SQLitePreparedStatement state = database.executeFast("UPDATE chat_pinned_count SET count = ? WHERE uid = ?"); + state.requery(); + state.bindInteger(1, Math.max(0, count - updatedCount)); + state.bindLong(2, -channelId); + state.step(); + state.dispose(); + } + cursor.dispose(); + } + database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE uid = %d AND mid <= %d", -channelId, maxMessageId)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE uid = %d AND mid <= %d", -channelId, maxMessageId)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", -channelId)).stepThis().dispose(); @@ -9572,6 +9769,7 @@ public class MessagesStorage extends BaseController { //load_type == 3 ? load around message //load_type == 4 ? load around date ArrayList filesToDelete = new ArrayList<>(); + ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?)"); @@ -9612,7 +9810,7 @@ public class MessagesStorage extends BaseController { sameMedia = oldMessage.media.document.id == message.media.document.id; } if (!sameMedia) { - addFilesToDelete(oldMessage, filesToDelete, idsToDelete, false); + addFilesToDelete(oldMessage, filesToDelete, idsToDelete, namesToDelete, false); } } boolean oldMention = cursor.intValue(3) != 0; @@ -9786,6 +9984,7 @@ public class MessagesStorage extends BaseController { getMediaDataController().putBotKeyboard(dialog_id, botKeyboard); } deleteFromDownloadQueue(idsToDelete, false); + AndroidUtilities.runOnUIThread(() -> getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, 0); putUsersInternal(messages.users); putChatsInternal(messages.chats); @@ -9833,6 +10032,25 @@ public class MessagesStorage extends BaseController { if (message.action.chat_id != 0 && !chatsToLoad.contains(message.action.chat_id)) { chatsToLoad.add(message.action.chat_id); } + if (message.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + TLRPC.TL_messageActionGeoProximityReached action = (TLRPC.TL_messageActionGeoProximityReached) message.action; + Integer id = MessageObject.getPeerId(action.from_id); + if (id > 0) { + if (!usersToLoad.contains(id)) { + usersToLoad.add(id); + } + } else if (!chatsToLoad.contains(-id)) { + chatsToLoad.add(-id); + } + id = MessageObject.getPeerId(action.to_id); + if (id > 0) { + if (!usersToLoad.contains(id)) { + usersToLoad.add(id); + } + } else if (!chatsToLoad.contains(-id)) { + chatsToLoad.add(-id); + } + } if (!message.action.users.isEmpty()) { for (int a = 0; a < message.action.users.size(); a++) { Integer uid = message.action.users.get(a); @@ -10799,6 +11017,9 @@ public class MessagesStorage extends BaseController { try { String savedMessages = LocaleController.getString("SavedMessages", R.string.SavedMessages).toLowerCase(); String search1 = query.trim().toLowerCase(); + if (TextUtils.isEmpty(search1)) { + return; + } String search2 = LocaleController.getInstance().getTranslitString(search1); if (search1.equals(search2) || search2.length() == 0) { search2 = null; @@ -10815,7 +11036,7 @@ public class MessagesStorage extends BaseController { int resultCount = 0; LongSparseArray dialogsResult = new LongSparseArray<>(); - SQLiteCursor cursor = null; + SQLiteCursor cursor; if (folderId >= 0) { cursor = getDatabase().queryFinalized("SELECT did, date FROM dialogs WHERE folder_id = ? ORDER BY date DESC LIMIT 600", folderId); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java index ea8f66ca7..6b452af77 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java @@ -22,7 +22,7 @@ import java.util.zip.ZipFile; public class NativeLoader { - private final static int LIB_VERSION = 33; + private final static int LIB_VERSION = 34; private final static String LIB_NAME = "tmessages." + LIB_VERSION; private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so"; private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 9fc5c0e28..27568aeb1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -13,6 +13,7 @@ import android.util.SparseArray; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; public class NotificationCenter { @@ -63,7 +64,7 @@ public class NotificationCenter { public static final int didSetOrRemoveTwoStepPassword = totalEvents++; public static final int didRemoveTwoStepPassword = totalEvents++; public static final int replyMessagesDidLoad = totalEvents++; - public static final int pinnedMessageDidLoad = totalEvents++; + public static final int didLoadPinnedMessages = totalEvents++; public static final int newSessionReceived = totalEvents++; public static final int didReceivedWebpages = totalEvents++; public static final int didReceivedWebpagesInUpdates = totalEvents++; @@ -74,6 +75,7 @@ public class NotificationCenter { public static final int messagesReadContent = totalEvents++; public static final int botInfoDidLoad = totalEvents++; public static final int userInfoDidLoad = totalEvents++; + public static final int pinnedInfoDidLoad = totalEvents++; public static final int botKeyboardDidLoad = totalEvents++; public static final int chatSearchResultsAvailable = totalEvents++; public static final int chatSearchResultsLoading = totalEvents++; @@ -201,6 +203,8 @@ public class NotificationCenter { private SparseArray> removeAfterBroadcast = new SparseArray<>(); private SparseArray> addAfterBroadcast = new SparseArray<>(); private ArrayList delayedPosts = new ArrayList<>(10); + private ArrayList delayedRunnables = new ArrayList<>(10); + private ArrayList delayedRunnablesTmp = new ArrayList<>(10); private ArrayList delayedPostsTmp = new ArrayList<>(10); private ArrayList postponeCallbackList = new ArrayList<>(10); @@ -209,6 +213,8 @@ public class NotificationCenter { private int animationInProgressCount; private int animationInProgressPointer = 1; + HashSet heavyOperationsCounter = new HashSet<>(); + private final HashMap allowedNotifications = new HashMap<>(); public interface NotificationCenterDelegate { @@ -264,14 +270,21 @@ public class NotificationCenter { } public int setAnimationInProgress(int oldIndex, int[] allowedNotifications) { + return setAnimationInProgress(oldIndex, allowedNotifications, true); + } + + public int setAnimationInProgress(int oldIndex, int[] allowedNotifications, boolean stopHeavyOperations) { onAnimationFinish(oldIndex); - if (animationInProgressCount == 0) { + if (heavyOperationsCounter.isEmpty() && stopHeavyOperations) { NotificationCenter.getGlobalInstance().postNotificationName(stopAllHeavyOperations, 512); } animationInProgressCount++; animationInProgressPointer++; + if (stopHeavyOperations) { + heavyOperationsCounter.add(animationInProgressPointer); + } if (allowedNotifications == null) { allowedNotifications = new int[0]; } @@ -294,8 +307,13 @@ public class NotificationCenter { int[] notifications = allowedNotifications.remove(index); if (notifications != null) { animationInProgressCount--; + if (!heavyOperationsCounter.isEmpty()) { + heavyOperationsCounter.remove(index); + if (heavyOperationsCounter.isEmpty()) { + NotificationCenter.getGlobalInstance().postNotificationName(startAllHeavyOperations, 512); + } + } if (animationInProgressCount == 0) { - NotificationCenter.getGlobalInstance().postNotificationName(startAllHeavyOperations, 512); runDelayedNotifications(); } } @@ -312,6 +330,16 @@ public class NotificationCenter { } delayedPostsTmp.clear(); } + + if (!delayedRunnables.isEmpty()) { + delayedRunnablesTmp.clear(); + delayedRunnablesTmp.addAll(delayedRunnables); + delayedRunnables.clear(); + for (int a = 0; a < delayedRunnablesTmp.size(); a++) { + delayedRunnablesTmp.get(a).run(); + } + delayedRunnablesTmp.clear(); + } } public boolean isAnimationInProgress() { @@ -327,7 +355,7 @@ public class NotificationCenter { if (!allowDuringAnimation && !allowedNotifications.isEmpty()) { int size = allowedNotifications.size(); int allowedCount = 0; - for(Integer key : allowedNotifications.keySet()) { + for (Integer key : allowedNotifications.keySet()) { int[] allowed = allowedNotifications.get(key); if (allowed != null) { for (int a = 0; a < allowed.length; a++) { @@ -344,7 +372,7 @@ public class NotificationCenter { } if (id == startAllHeavyOperations) { Integer flags = (Integer) args[0]; - currentHeavyOperationFlags &=~ flags; + currentHeavyOperationFlags &= ~flags; } else if (id == stopAllHeavyOperations) { Integer flags = (Integer) args[0]; currentHeavyOperationFlags |= flags; @@ -483,4 +511,12 @@ public class NotificationCenter { public interface PostponeNotificationCallback { boolean needPostpone(int id, int currentAccount, Object[] args); } + + public void doOnIdle(Runnable runnable) { + if (isAnimationInProgress()) { + delayedRunnables.add(runnable); + } else { + runnable.run(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 6a5e1451d..59f530a88 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -1242,12 +1242,13 @@ public class NotificationsController extends BaseController { } return messageObject.messageOwner.message; } + int selfUsedId = getUserConfig().getClientUserId(); if (fromId == 0) { fromId = messageObject.getFromChatId(); if (fromId == 0) { fromId = -chat_id; } - } else if (fromId == getUserConfig().getClientUserId()) { + } else if (fromId == selfUsedId) { fromId = messageObject.getFromChatId(); } @@ -1321,7 +1322,9 @@ public class NotificationsController extends BaseController { if (dialogPreviewEnabled && (chat_id == 0 && fromId != 0 && preferences.getBoolean("EnablePreviewAll", true) || chat_id != 0 && (!isChannel && preferences.getBoolean("EnablePreviewGroup", true) || isChannel && preferences.getBoolean("EnablePreviewChannel", true)))) { if (messageObject.messageOwner instanceof TLRPC.TL_messageService) { userName[0] = null; - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + return messageObject.messageText.toString(); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { return LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { return LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, name); @@ -1345,7 +1348,7 @@ public class NotificationsController extends BaseController { if (messageObject.messageOwner.peer_id.channel_id != 0 && !chat.megagroup) { return LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title); } else { - if (singleUserId == getUserConfig().getClientUserId()) { + if (singleUserId == selfUsedId) { return LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); @@ -1396,7 +1399,7 @@ public class NotificationsController extends BaseController { } } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser) { - if (messageObject.messageOwner.action.user_id == getUserConfig().getClientUserId()) { + if (messageObject.messageOwner.action.user_id == selfUsedId) { return LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, name, chat.title); } else if (messageObject.messageOwner.action.user_id == fromId) { return LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, name, chat.title); @@ -1490,7 +1493,7 @@ public class NotificationsController extends BaseController { return LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); } } - } else { + } else if (chat != null) { if (messageObject.replyMessageObject == null) { return LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); } else { @@ -1562,6 +1565,78 @@ public class NotificationsController extends BaseController { return LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); } } + } else { + if (messageObject.replyMessageObject == null) { + return LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + } else { + MessageObject object = messageObject.replyMessageObject; + if (object.isMusic()) { + return LocaleController.formatString("NotificationActionPinnedMusicUser", R.string.NotificationActionPinnedMusicUser, name); + } else if (object.isVideo()) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDCF9 " + object.messageOwner.message; + return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + return LocaleController.formatString("NotificationActionPinnedVideoUser", R.string.NotificationActionPinnedVideoUser, name); + } + } else if (object.isGif()) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83C\uDFAC " + object.messageOwner.message; + return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + return LocaleController.formatString("NotificationActionPinnedGifUser", R.string.NotificationActionPinnedGifUser, name); + } + } else if (object.isVoice()) { + return LocaleController.formatString("NotificationActionPinnedVoiceUser", R.string.NotificationActionPinnedVoiceUser, name); + } else if (object.isRoundVideo()) { + return LocaleController.formatString("NotificationActionPinnedRoundUser", R.string.NotificationActionPinnedRoundUser, name); + } else if (object.isSticker() || object.isAnimatedSticker()) { + String emoji = object.getStickerEmoji(); + if (emoji != null) { + return LocaleController.formatString("NotificationActionPinnedStickerEmojiUser", R.string.NotificationActionPinnedStickerEmojiUser, name, emoji); + } else { + return LocaleController.formatString("NotificationActionPinnedStickerUser", R.string.NotificationActionPinnedStickerUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDCCE " + object.messageOwner.message; + return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + return LocaleController.formatString("NotificationActionPinnedFileUser", R.string.NotificationActionPinnedFileUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { + return LocaleController.formatString("NotificationActionPinnedGeoUser", R.string.NotificationActionPinnedGeoUser, name); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { + return LocaleController.formatString("NotificationActionPinnedGeoLiveUser", R.string.NotificationActionPinnedGeoLiveUser, name); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; + return LocaleController.formatString("NotificationActionPinnedContactUser", R.string.NotificationActionPinnedContactUser, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + if (mediaPoll.poll.quiz) { + return LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question); + } else { + return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDDBC " + object.messageOwner.message; + return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + return LocaleController.formatString("NotificationActionPinnedPhotoUser", R.string.NotificationActionPinnedPhotoUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { + return LocaleController.formatString("NotificationActionPinnedGameUser", R.string.NotificationActionPinnedGameUser, name); + } else if (object.messageText != null && object.messageText.length() > 0) { + CharSequence message = object.messageText; + if (message.length() > 20) { + message = message.subSequence(0, 20) + "..."; + } + return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + return LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + } + } } } } else { @@ -1736,7 +1811,9 @@ public class NotificationsController extends BaseController { if (chat_id == 0 && from_id != 0) { if (dialogPreviewEnabled && preferences.getBoolean("EnablePreviewAll", true)) { if (messageObject.messageOwner instanceof TLRPC.TL_messageService) { - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + msg = messageObject.messageText.toString(); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { msg = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { msg = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, name); @@ -2004,7 +2081,7 @@ public class NotificationsController extends BaseController { msg = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); } } - } else { + } else if (chat != null) { if (messageObject.replyMessageObject == null) { msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); } else { @@ -2076,6 +2153,78 @@ public class NotificationsController extends BaseController { msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); } } + } else { + if (messageObject.replyMessageObject == null) { + msg = LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + } else { + MessageObject object = messageObject.replyMessageObject; + if (object.isMusic()) { + msg = LocaleController.formatString("NotificationActionPinnedMusicUser", R.string.NotificationActionPinnedMusicUser, name); + } else if (object.isVideo()) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDCF9 " + object.messageOwner.message; + msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + msg = LocaleController.formatString("NotificationActionPinnedVideoUser", R.string.NotificationActionPinnedVideoUser, name); + } + } else if (object.isGif()) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83C\uDFAC " + object.messageOwner.message; + msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + msg = LocaleController.formatString("NotificationActionPinnedGifUser", R.string.NotificationActionPinnedGifUser, name); + } + } else if (object.isVoice()) { + msg = LocaleController.formatString("NotificationActionPinnedVoiceUser", R.string.NotificationActionPinnedVoiceUser, name); + } else if (object.isRoundVideo()) { + msg = LocaleController.formatString("NotificationActionPinnedRoundUser", R.string.NotificationActionPinnedRoundUser, name); + } else if (object.isSticker() || object.isAnimatedSticker()) { + String emoji = object.getStickerEmoji(); + if (emoji != null) { + msg = LocaleController.formatString("NotificationActionPinnedStickerEmojiUser", R.string.NotificationActionPinnedStickerEmojiUser, name, emoji); + } else { + msg = LocaleController.formatString("NotificationActionPinnedStickerUser", R.string.NotificationActionPinnedStickerUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDCCE " + object.messageOwner.message; + msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + msg = LocaleController.formatString("NotificationActionPinnedFileUser", R.string.NotificationActionPinnedFileUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { + msg = LocaleController.formatString("NotificationActionPinnedGeoUser", R.string.NotificationActionPinnedGeoUser, name); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { + msg = LocaleController.formatString("NotificationActionPinnedGeoLiveUser", R.string.NotificationActionPinnedGeoLiveUser, name); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationActionPinnedContactUser", R.string.NotificationActionPinnedContactUser, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + if (mediaPoll.poll.quiz) { + msg = LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question); + } else { + msg = LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { + if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { + String message = "\uD83D\uDDBC " + object.messageOwner.message; + msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + msg = LocaleController.formatString("NotificationActionPinnedPhotoUser", R.string.NotificationActionPinnedPhotoUser, name); + } + } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { + msg = LocaleController.formatString("NotificationActionPinnedGameUser", R.string.NotificationActionPinnedGameUser, name); + } else if (object.messageText != null && object.messageText.length() > 0) { + CharSequence message = object.messageText; + if (message.length() > 20) { + message = message.subSequence(0, 20) + "..."; + } + msg = LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + } else { + msg = LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + } + } } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { msg = messageObject.messageText.toString(); @@ -3839,7 +3988,11 @@ public class NotificationsController extends BaseController { } } if (!unsupportedNotificationShortcut()) { - ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, ids); + try { + ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, ids); + } catch (Exception e) { + FileLog.e(e); + } } for (int a = 0; a < oldIdsWear.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 9fa325828..487efcb85 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -299,6 +299,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe public TLRPC.EncryptedChat encryptedChat; public VideoEditedInfo videoEditedInfo; public boolean performMediaUpload; + + public boolean retriedToSend; public int topMessageId; @@ -377,7 +379,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else if (request.request instanceof TLRPC.TL_messages_sendMultiMedia) { performSendMessageRequestMulti((TLRPC.TL_messages_sendMultiMedia) request.request, request.msgObjs, request.originalPaths, request.parentObjects, request.delayedMessage, request.scheduled); } else { - performSendMessageRequest(request.request, request.msgObj, request.originalPath, request.delayedMessage, request.parentObject, request.scheduled); + performSendMessageRequest(request.request, request.msgObj, request.originalPath, request.delayedMessage, request.parentObject, null, request.scheduled); } } requests = null; @@ -471,19 +473,19 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (file != null && media != null) { if (message.type == 0) { media.file = file; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, message, true, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, message, true, null, message.parentObject, null, message.scheduled); } else if (message.type == 1) { if (media.file == null) { media.file = file; if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); } } else { media.thumb = file; media.flags |= 4; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); } } else if (message.type == 2) { if (media.file == null) { @@ -491,16 +493,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); } } else { media.thumb = file; media.flags |= 4; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); } } else if (message.type == 3) { media.file = file; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); } else if (message.type == 4) { if (media instanceof TLRPC.TL_inputMediaUploadedDocument) { if (media.file == null) { @@ -876,6 +878,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe message.messageObjects.remove(index); message.messages.remove(index); message.originalPaths.remove(index); + message.parentObjects.remove(index); if (message.sendRequest != null) { TLRPC.TL_messages_sendMultiMedia request = (TLRPC.TL_messages_sendMultiMedia) message.sendRequest; request.multi_media.remove(index); @@ -1114,7 +1117,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe arr.add(message); getMessagesStorage().putMessages(arr, false, true, false, 0, false); - performSendMessageRequest(req, newMsgObj, null, null, null, false); + performSendMessageRequest(req, newMsgObj, null, null, null, null, false); } public void sendSticker(TLRPC.Document document, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, Object parentObject, boolean notify, int scheduleDate) { @@ -1339,8 +1342,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } } if (msgObj.messageOwner.post_author != null) { - newMsg.fwd_from.post_author = msgObj.messageOwner.post_author; - newMsg.fwd_from.flags |= 8; + /*newMsg.fwd_from.post_author = msgObj.messageOwner.post_author; + newMsg.fwd_from.flags |= 8;*/ } else if (!msgObj.isOutOwner() && fromId > 0 && msgObj.messageOwner.post) { TLRPC.User signUser = getMessagesController().getUser(fromId); if (signUser != null) { @@ -1998,32 +2001,32 @@ public class SendMessagesHelper extends BaseController implements NotificationCe reqSend = request; if (type == 1) { - performSendMessageRequest(reqSend, messageObject, null, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, null, delayedMessage, parentObject, params, messageObject.scheduled); } else if (type == 2) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, null, true, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, originalPath, null, true, delayedMessage, parentObject, params, messageObject.scheduled); } } else if (type == 3) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, params, messageObject.scheduled); } } else if (type == 6) { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, params, messageObject.scheduled); } else if (type == 7) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, params, messageObject.scheduled); } } else if (type == 8) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, params, messageObject.scheduled); } } } @@ -3033,15 +3036,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsg.from_id = newMsg.peer_id; } newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - newMsgObj = new MessageObject(currentAccount, newMsg, replyToMsg, true, true); - newMsgObj.wasJustSent = true; - newMsgObj.scheduled = scheduleDate != 0; - if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) { - newMsgObj.attachPathExists = true; - } - if (newMsgObj.videoEditedInfo != null && videoEditedInfo == null) { - videoEditedInfo = newMsgObj.videoEditedInfo; - } long groupId = 0; boolean isFinalGroupMedia = false; @@ -3055,6 +3049,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe isFinalGroupMedia = params.get("final") != null; } + newMsgObj = new MessageObject(currentAccount, newMsg, replyToMsg, true, true); + newMsgObj.wasJustSent = true; + newMsgObj.scheduled = scheduleDate != 0; + if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) { + newMsgObj.attachPathExists = true; + } + if (newMsgObj.videoEditedInfo != null && videoEditedInfo == null) { + videoEditedInfo = newMsgObj.videoEditedInfo; + } + if (groupId == 0) { ArrayList objArr = new ArrayList<>(); objArr.add(newMsgObj); @@ -3117,7 +3121,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe reqSend.schedule_date = scheduleDate; reqSend.flags |= 1024; } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); if (retryMessageObject == null) { getMediaDataController().cleanDraft(peer, replyToTopMsg != null ? replyToTopMsg.getId() : 0, false); } @@ -3171,6 +3175,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe inputMedia = new TLRPC.TL_inputMediaGeoLive(); inputMedia.period = location.period; inputMedia.flags |= 2; + if (location.heading != 0) { + inputMedia.heading = location.heading; + inputMedia.flags |= 4; + } + if (location.proximity_notification_radius != 0) { + inputMedia.proximity_notification_radius = location.proximity_notification_radius; + inputMedia.flags |= 8; + } } else { inputMedia = new TLRPC.TL_inputMediaGeoPoint(); } @@ -3301,6 +3313,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (forceNoSoundVideo || !TextUtils.isEmpty(path) && path.toLowerCase().endsWith("mp4") && (params == null || params.containsKey("forceDocument"))) { uploadedMedia.nosound_video = true; } + uploadedMedia.force_file = params != null && params.containsKey("forceDocument"); uploadedMedia.mime_type = document.mime_type; uploadedMedia.attributes = document.attributes; } else { @@ -3322,18 +3335,20 @@ public class SendMessagesHelper extends BaseController implements NotificationCe inputMedia = media; } if (!http && uploadedMedia != null) { - delayedMessage = new DelayedMessage(peer); - delayedMessage.originalPath = originalPath; - delayedMessage.type = 2; - delayedMessage.obj = newMsgObj; + if (delayedMessage == null) { + delayedMessage = new DelayedMessage(peer); + delayedMessage.type = 2; + delayedMessage.obj = newMsgObj; + delayedMessage.originalPath = originalPath; + delayedMessage.parentObject = parentObject; + delayedMessage.scheduled = scheduleDate != 0; + } + delayedMessage.inputUploadMedia = uploadedMedia; + delayedMessage.performMediaUpload = performMediaUpload; if (!document.thumbs.isEmpty()) { delayedMessage.photoSize = document.thumbs.get(0); delayedMessage.locationParent = document; } - delayedMessage.parentObject = parentObject; - delayedMessage.inputUploadMedia = uploadedMedia; - delayedMessage.performMediaUpload = performMediaUpload; - delayedMessage.scheduled = scheduleDate != 0; } } else if (type == 8) { TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); @@ -3455,35 +3470,35 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (groupId != 0) { performSendDelayedMessage(delayedMessage); } else if (type == 1) { - performSendMessageRequest(reqSend, newMsgObj, null, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, null, delayedMessage, parentObject, params, scheduleDate != 0); } else if (type == 2) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, null, true, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, null, true, delayedMessage, parentObject, params, scheduleDate != 0); } } else if (type == 3) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, params, scheduleDate != 0); } } else if (type == 6) { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, params, scheduleDate != 0); } else if (type == 7) { if (performMediaUpload && delayedMessage != null) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, params, scheduleDate != 0); } } else if (type == 8) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, params, scheduleDate != 0); } } else if (type == 10 || type == 11) { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, params, scheduleDate != 0); } } else { TLRPC.TL_decryptedMessage reqSend; @@ -3685,24 +3700,28 @@ public class SendMessagesHelper extends BaseController implements NotificationCe reqSend.media.size = document.size; reqSend.media.mime_type = document.mime_type; - if (document.key == null) { - delayedMessage = new DelayedMessage(peer); - delayedMessage.originalPath = originalPath; - delayedMessage.sendEncryptedRequest = reqSend; - delayedMessage.type = 2; - delayedMessage.obj = newMsgObj; - if (params != null && params.containsKey("parentObject")) { - delayedMessage.parentObject = params.get("parentObject"); - } else { - delayedMessage.parentObject = parentObject; + if (document.key == null || groupId != 0) { + if (delayedMessage == null) { + delayedMessage = new DelayedMessage(peer); + delayedMessage.encryptedChat = encryptedChat; + delayedMessage.type = 2; + delayedMessage.sendEncryptedRequest = reqSend; + delayedMessage.originalPath = originalPath; + delayedMessage.obj = newMsgObj; + if (params != null && params.containsKey("parentObject")) { + delayedMessage.parentObject = params.get("parentObject"); + } else { + delayedMessage.parentObject = parentObject; + } + delayedMessage.performMediaUpload = true; + delayedMessage.scheduled = scheduleDate != 0; } - delayedMessage.encryptedChat = encryptedChat; - delayedMessage.performMediaUpload = true; if (path != null && path.length() > 0 && path.startsWith("http")) { delayedMessage.httpLocation = path; } - delayedMessage.scheduled = scheduleDate != 0; - performSendDelayedMessage(delayedMessage); + if (groupId == 0) { + performSendDelayedMessage(delayedMessage); + } } else { TLRPC.TL_inputEncryptedFile encryptedFile = new TLRPC.TL_inputEncryptedFile(); encryptedFile.id = document.id; @@ -3755,7 +3774,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe delayedMessage.performMediaUpload = true; request.messages.add(reqSend); TLRPC.TL_inputEncryptedFile encryptedFile = new TLRPC.TL_inputEncryptedFile(); - encryptedFile.id = type == 3 ? 1 : 0; + encryptedFile.id = type == 3 || type == 7 ? 1 : 0; request.files.add(encryptedFile); performSendDelayedMessage(delayedMessage); } @@ -3792,7 +3811,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe reqSend.id.add(retryMessageObject.messageOwner.fwd_from.channel_post); } } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); } else if (type == 9) { TLRPC.TL_messages_sendInlineBotResult reqSend = new TLRPC.TL_messages_sendInlineBotResult(); reqSend.peer = sendToPeer; @@ -3813,7 +3832,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe reqSend.clear_draft = true; getMediaDataController().cleanDraft(peer, replyToTopMsg != null ? replyToTopMsg.getId() : 0, false); } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); } } catch (Exception e) { FileLog.e(e); @@ -4058,7 +4077,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe getFileLoader().uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo); } putToUploadingMessages(messageObject); - } else { + } else if (message.photoSize != null) { String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg"; putToDelayedMessages(location, message); message.extraHashMap.put(location + "_o", documentLocation); @@ -4399,8 +4418,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe ArrayList arrayList = new ArrayList<>(parentObjects); getFileRefController().requestReference(arrayList, req, msgObjs, originalPaths, arrayList, delayedMessage, scheduled); return; - } else if (delayedMessage != null) { + } else if (delayedMessage != null && !delayedMessage.retriedToSend) { + delayedMessage.retriedToSend = true; AndroidUtilities.runOnUIThread(() -> { + boolean hasEmptyFile = false; for (int a = 0, size = req.multi_media.size(); a < size; a++) { if (delayedMessage.parentObjects.get(a) == null) { continue; @@ -4416,8 +4437,21 @@ public class SendMessagesHelper extends BaseController implements NotificationCe delayedMessage.httpLocation = delayedMessage.httpLocations.get(a); delayedMessage.photoSize = delayedMessage.locations.get(a); delayedMessage.performMediaUpload = true; + if (request.media.file == null || delayedMessage.photoSize != null) { + hasEmptyFile = true; + } performSendDelayedMessage(delayedMessage, a); } + if (!hasEmptyFile) { + for (int i = 0; i < msgObjs.size(); i++) { + TLRPC.Message newMsgObj = msgObjs.get(i).messageOwner; + getMessagesStorage().markMessageAsSendError(newMsgObj, scheduled); + newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; + getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); + processSentMessage(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); + } + } }); return; } @@ -4561,8 +4595,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe }, null, ConnectionsManager.RequestFlagCanCompress | ConnectionsManager.RequestFlagInvokeAfter); } - private void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage delayedMessage, Object parentObject, boolean scheduled) { - performSendMessageRequest(req, msgObj, originalPath, null, false, delayedMessage, parentObject, scheduled); + private void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage delayedMessage, Object parentObject, HashMap params, boolean scheduled) { + performSendMessageRequest(req, msgObj, originalPath, null, false, delayedMessage, parentObject, params, scheduled); } private DelayedMessage findMaxDelayedMessageForMessageId(int messageId, long dialogId) { @@ -4592,7 +4626,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return maxDelayedMessage; } - protected void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage parentMessage, boolean check, DelayedMessage delayedMessage, Object parentObject, boolean scheduled) { + protected void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage parentMessage, boolean check, DelayedMessage delayedMessage, Object parentObject, HashMap params, boolean scheduled) { if (!(req instanceof TLRPC.TL_messages_editMessage)) { if (check) { DelayedMessage maxDelayedMessage = findMaxDelayedMessageForMessageId(msgObj.getId(), msgObj.getDialogId()); @@ -4811,8 +4845,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe existFlags = 0; } - if (MessageObject.isLiveLocationMessage(newMsgObj)) { - getLocationController().addSharingLocation(newMsgObj.dialog_id, newMsgObj.id, newMsgObj.media.period, newMsgObj); + if (MessageObject.isLiveLocationMessage(newMsgObj) && newMsgObj.via_bot_id == 0 && TextUtils.isEmpty(newMsgObj.via_bot_name)) { + getLocationController().addSharingLocation(newMsgObj.dialog_id, newMsgObj.id, newMsgObj.media.period, newMsgObj.media.proximity_notification_radius, newMsgObj); } if (!isSentError) { @@ -5184,7 +5218,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } } - private static boolean prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, boolean forceDocument, boolean notify, int scheduleDate) { + private static boolean prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, boolean forceDocument, boolean notify, int scheduleDate, Boolean[] withThumb) { if ((path == null || path.length() == 0) && uri == null) { return false; } @@ -5363,7 +5397,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { document.mime_type = "application/octet-stream"; } - if (document.mime_type.equals("image/gif") && (editingMessageObject == null || editingMessageObject.getGroupIdForUse() == 0)) { + if (!forceDocument && document.mime_type.equals("image/gif") && (editingMessageObject == null || editingMessageObject.getGroupIdForUse() == 0)) { try { Bitmap bitmap = ImageLoader.loadBitmap(f.getAbsolutePath(), null, 90, 90, true); if (bitmap != null) { @@ -5418,6 +5452,22 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (parentFinal != null) { params.put("parentObject", parentFinal); } + Boolean prevWithThumb = false; + if (withThumb != null) { + prevWithThumb = withThumb[0]; + withThumb[0] = document.mime_type != null && (document.mime_type.toLowerCase().startsWith("image/") || document.mime_type.toLowerCase().startsWith("video/mp4")) || MessageObject.canPreviewDocument(document); + } + if (groupId != null) { + if (withThumb != null && prevWithThumb != null && prevWithThumb != withThumb[0]) { + finishGroup(accountInstance, groupId[0], scheduleDate); + groupId[0] = Utilities.random.nextLong(); + } + params.put("groupId", "" + groupId[0]); + if (isGroupFinal) { + params.put("final", "1"); + } + } + AndroidUtilities.runOnUIThread(() -> { if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, null, documentFinal, pathFinal, params, false, parentFinal); @@ -5450,13 +5500,27 @@ public class SendMessagesHelper extends BaseController implements NotificationCe @UiThread public static void prepareSendingAudioDocuments(AccountInstance accountInstance, ArrayList messageObjects, String caption, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, MessageObject editingMessageObject, boolean notify, int scheduleDate) { new Thread(() -> { - int size = messageObjects.size(); - for (int a = 0; a < size; a++) { + int count = messageObjects.size(); + long groupId = 0; + int mediaCount = 0; + for (int a = 0; a < count; a++) { final MessageObject messageObject = messageObjects.get(a); String originalPath = messageObject.messageOwner.attachPath; final File f = new File(originalPath); boolean isEncrypted = (int) dialogId == 0; + int enryptedLayer = 0; + if (isEncrypted) { + int high_id = (int) (dialogId >> 32); + TLRPC.EncryptedChat encryptedChat = accountInstance.getMessagesController().getEncryptedChat(high_id); + if (encryptedChat != null) { + enryptedLayer = AndroidUtilities.getPeerLayerVersion(encryptedChat.layer); + } + } + if ((!isEncrypted || enryptedLayer >= 73) && count > 1 && mediaCount % 10 == 0) { + groupId = Utilities.random.nextLong(); + mediaCount = 0; + } if (originalPath != null) { originalPath += "audio" + f.length(); @@ -5494,6 +5558,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (parentFinal != null) { params.put("parentObject", parentFinal); } + mediaCount++; + params.put("groupId", "" + groupId); + if (mediaCount == 10 || a == count - 1) { + params.put("final", "1"); + } AndroidUtilities.runOnUIThread(() -> { if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, null, documentFinal, messageObject.messageOwner.attachPath, params, false, parentFinal); @@ -5505,6 +5574,26 @@ public class SendMessagesHelper extends BaseController implements NotificationCe }).start(); } + private static void finishGroup(AccountInstance accountInstance, long groupId, int scheduleDate) { + AndroidUtilities.runOnUIThread(() -> { + SendMessagesHelper instance = accountInstance.getSendMessagesHelper(); + ArrayList arrayList = instance.delayedMessages.get("group_" + groupId); + if (arrayList != null && !arrayList.isEmpty()) { + + DelayedMessage message = arrayList.get(0); + + MessageObject prevMessage = message.messageObjects.get(message.messageObjects.size() - 1); + message.finalGroupMessage = prevMessage.getId(); + prevMessage.messageOwner.params.put("final", "1"); + + TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); + messagesRes.messages.add(prevMessage.messageOwner); + accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduleDate != 0); + instance.sendReadyToSendGroup(message, true, true); + } + }); + } + @UiThread public static void prepareSendingDocuments(AccountInstance accountInstance, ArrayList paths, ArrayList originalPaths, ArrayList uris, String caption, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, InputContentInfoCompat inputContent, MessageObject editingMessageObject, boolean notify, int scheduleDate) { if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) { @@ -5512,20 +5601,62 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } new Thread(() -> { boolean error = false; + long[] groupId = new long[1]; + int mediaCount = 0; + Boolean[] withThumb = new Boolean[1]; + + boolean isEncrypted = (int) dialogId == 0; + int enryptedLayer = 0; + if (isEncrypted) { + int high_id = (int) (dialogId >> 32); + TLRPC.EncryptedChat encryptedChat = accountInstance.getMessagesController().getEncryptedChat(high_id); + if (encryptedChat != null) { + enryptedLayer = AndroidUtilities.getPeerLayerVersion(encryptedChat.layer); + } + } + if (paths != null) { - for (int a = 0; a < paths.size(); a++) { + int count = paths.size(); + for (int a = 0; a < count; a++) { final String captionFinal = a == 0 ? caption : null; - if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, false, notify, scheduleDate)) { + if (!isEncrypted && count > 1 && mediaCount % 10 == 0) { + if (groupId[0] != 0) { + finishGroup(accountInstance, groupId[0], scheduleDate); + } + groupId[0] = Utilities.random.nextLong(); + mediaCount = 0; + } + mediaCount++; + long prevGroupId = groupId[0]; + if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, true, notify, scheduleDate, withThumb)) { error = true; } + if (prevGroupId != groupId[0]) { + mediaCount = 1; + } } } if (uris != null) { + groupId[0] = 0; + mediaCount = 0; + int count = uris.size(); for (int a = 0; a < uris.size(); a++) { final String captionFinal = a == 0 && (paths == null || paths.size() == 0) ? caption : null; - if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, false, notify, scheduleDate)) { + if (!isEncrypted && count > 1 && mediaCount % 10 == 0) { + if (groupId[0] != 0) { + finishGroup(accountInstance, groupId[0], scheduleDate); + } + groupId[0] = Utilities.random.nextLong(); + mediaCount = 0; + } + mediaCount++; + long prevGroupId = groupId[0]; + if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, true, notify, scheduleDate, withThumb)) { error = true; } + if (prevGroupId != groupId[0]) { + mediaCount = 1; + } } } if (inputContent != null) { @@ -5546,8 +5677,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe @UiThread public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate) { + prepareSendingPhoto(accountInstance, imageFilePath, null, imageUri, dialogId, replyToMsg, replyToTopMsg, caption, entities, stickers, inputContent, ttl, editingMessageObject, null, notify, scheduleDate); + } + + @UiThread + public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, String thumbFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { SendingMediaInfo info = new SendingMediaInfo(); info.path = imageFilePath; + info.thumbPath = thumbFilePath; info.uri = imageUri; if (caption != null) { info.caption = caption.toString(); @@ -5557,6 +5694,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (stickers != null) { info.masks = new ArrayList<>(stickers); } + info.videoEditedInfo = videoEditedInfo; ArrayList infos = new ArrayList<>(); infos.add(info); prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, inputContent, false, false, editingMessageObject, notify, scheduleDate); @@ -5858,14 +5996,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } accountInstance.getSendMessagesHelper().sendMessage(venue, dialogId, replyToMsg, replyToTopMsg, result.send_message.reply_markup, params, notify, scheduleDate); } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaGeo) { - if (result.send_message.period != 0) { + if (result.send_message.period != 0 || result.send_message.proximity_notification_radius != 0) { TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); - location.period = result.send_message.period; + location.period = result.send_message.period != 0 ? result.send_message.period : 900; location.geo = result.send_message.geo; + location.heading = result.send_message.heading; + location.proximity_notification_radius = result.send_message.proximity_notification_radius; accountInstance.getSendMessagesHelper().sendMessage(location, dialogId, replyToMsg, replyToTopMsg, result.send_message.reply_markup, params, notify, scheduleDate); } else { TLRPC.TL_messageMediaGeo location = new TLRPC.TL_messageMediaGeo(); location.geo = result.send_message.geo; + location.heading = result.send_message.heading; accountInstance.getSendMessagesHelper().sendMessage(location, dialogId, replyToMsg, replyToTopMsg, result.send_message.reply_markup, params, notify, scheduleDate); } } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaContact) { @@ -6015,17 +6156,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } @UiThread - public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, InputContentInfoCompat inputContent, boolean forceDocument, boolean groupPhotos, MessageObject editingMessageObject, boolean notify, int scheduleDate) { + public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, InputContentInfoCompat inputContent, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate) { if (media.isEmpty()) { return; } for (int a = 0, N = media.size(); a < N; a++) { if (media.get(a).ttl > 0) { - groupPhotos = false; + groupMedia = false; break; } } - final boolean groupPhotosFinal = groupPhotos; + final boolean groupMediaFinal = groupMedia; mediaSendQueue.postRunnable(() -> { long beginTime = System.currentTimeMillis(); HashMap workers; @@ -6039,7 +6180,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe enryptedLayer = AndroidUtilities.getPeerLayerVersion(encryptedChat.layer); } } - if ((!isEncrypted || enryptedLayer >= 73) && !forceDocument && groupPhotosFinal) { + if ((!isEncrypted || enryptedLayer >= 73) && !forceDocument && groupMediaFinal) { workers = new HashMap<>(); for (int a = 0; a < count; a++) { final SendingMediaInfo info = media.get(a); @@ -6115,12 +6256,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe ArrayList> sendAsDocumentsEntities = null; String extension = null; - int photosCount = 0; + int mediaCount = 0; for (int a = 0; a < count; a++) { final SendingMediaInfo info = media.get(a); - if (groupPhotosFinal && (!isEncrypted || enryptedLayer >= 73) && count > 1 && photosCount % 10 == 0) { + if (groupMediaFinal && (!isEncrypted || enryptedLayer >= 73) && count > 1 && mediaCount % 10 == 0) { lastGroupId = groupId = Utilities.random.nextLong(); - photosCount = 0; + mediaCount = 0; } if (info.searchImage != null && info.videoEditedInfo == null) { if (info.searchImage.type == 1) { @@ -6153,7 +6294,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe document.attributes.add(fileName); document.size = info.searchImage.size; document.dc_id = 0; - if (cacheFile.toString().endsWith("mp4")) { + if (!forceDocument && cacheFile.toString().endsWith("mp4")) { document.mime_type = "video/mp4"; document.attributes.add(new TLRPC.TL_documentAttributeAnimated()); } else { @@ -6276,10 +6417,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (parentFinal != null) { params.put("parentObject", parentFinal); } - if (groupPhotosFinal) { - photosCount++; + if (groupMediaFinal) { + mediaCount++; params.put("groupId", "" + groupId); - if (photosCount == 10 || a == count -1) { + if (mediaCount == 10 || a == count -1) { params.put("final", "1"); lastGroupId = 0; } @@ -6439,10 +6580,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (parentFinal != null) { params.put("parentObject", parentFinal); } - if (!muted && groupPhotosFinal) { - photosCount++; + if (!muted && groupMediaFinal) { + mediaCount++; params.put("groupId", "" + groupId); - if (photosCount == 10 || a == count -1) { + if (mediaCount == 10 || a == count -1) { params.put("final", "1"); lastGroupId = 0; } @@ -6468,7 +6609,19 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } }); } else { - prepareSendingDocumentInternal(accountInstance, info.path, info.path, null, null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, editingMessageObject, forceDocument, notify, scheduleDate); + if (sendAsDocuments == null) { + sendAsDocuments = new ArrayList<>(); + sendAsDocumentsOriginal = new ArrayList<>(); + sendAsDocumentsCaptions = new ArrayList<>(); + sendAsDocumentsEntities = new ArrayList<>(); + sendAsDocumentsUri = new ArrayList<>(); + } + sendAsDocuments.add(info.path); + sendAsDocumentsOriginal.add(info.path); + sendAsDocumentsUri.add(info.uri); + sendAsDocumentsCaptions.add(info.caption); + sendAsDocumentsEntities.add(info.entities); + //prepareSendingDocumentInternal(accountInstance, info.path, info.path, null, null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, editingMessageObject, null, false, forceDocument, notify, scheduleDate, null); } } else { String originalPath = info.path; @@ -6620,7 +6773,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } try { - if (!groupPhotosFinal || media.size() == 1) { + if (!groupMediaFinal || media.size() == 1) { TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoFinal.sizes, AndroidUtilities.getPhotoSize()); if (currentPhotoObject != null) { keyFinal[0] = getKeyForPhotoSize(currentPhotoObject, bitmapFinal, false, false); @@ -6630,10 +6783,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe FileLog.e(e); } - if (groupPhotosFinal) { - photosCount++; + if (groupMediaFinal) { + mediaCount++; params.put("groupId", "" + groupId); - if (photosCount == 10 || a == count - 1) { + if (mediaCount == 10 || a == count - 1) { params.put("final", "1"); lastGroupId = 0; } @@ -6667,31 +6820,21 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } } if (lastGroupId != 0) { - final long lastGroupIdFinal = lastGroupId; - AndroidUtilities.runOnUIThread(() -> { - SendMessagesHelper instance = accountInstance.getSendMessagesHelper(); - ArrayList arrayList = instance.delayedMessages.get("group_" + lastGroupIdFinal); - if (arrayList != null && !arrayList.isEmpty()) { - - DelayedMessage message = arrayList.get(0); - - MessageObject prevMessage = message.messageObjects.get(message.messageObjects.size() - 1); - message.finalGroupMessage = prevMessage.getId(); - prevMessage.messageOwner.params.put("final", "1"); - - TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); - messagesRes.messages.add(prevMessage.messageOwner); - accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduleDate != 0); - instance.sendReadyToSendGroup(message, true, true); - } - }); + finishGroup(accountInstance, lastGroupId, scheduleDate); } if (inputContent != null) { inputContent.releasePermission(); } if (sendAsDocuments != null && !sendAsDocuments.isEmpty()) { - for (int a = 0; a < sendAsDocuments.size(); a++) { - prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, forceDocument, notify, scheduleDate); + long[] groupId2 = new long[1]; + int documentsCount = sendAsDocuments.size(); + for (int a = 0; a < documentsCount; a++) { + if (forceDocument && !isEncrypted && count > 1 && mediaCount % 10 == 0) { + groupId2[0] = Utilities.random.nextLong(); + mediaCount = 0; + } + mediaCount++; + prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, forceDocument, notify, scheduleDate, null); } } if (BuildVars.LOGS_ENABLED) { @@ -7100,7 +7243,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } }); } else { - prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, caption, entities, editingMessageObject, false, notify, scheduleDate); + prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, caption, entities, editingMessageObject, null, false, false, notify, scheduleDate, null); } }).start(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java index 513ffa95b..4787d818f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java @@ -388,7 +388,7 @@ public class TextureRenderer { for (int a = 0, N = mediaEntities.size(); a < N; a++) { VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); if (entity.ptr != 0) { - RLottieDrawable.getFrame(entity.ptr, (int) entity.currentFrame, stickerBitmap, 512, 512, stickerBitmap.getRowBytes()); + RLottieDrawable.getFrame(entity.ptr, (int) entity.currentFrame, stickerBitmap, 512, 512, stickerBitmap.getRowBytes(), true); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, stickerTexture[0]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, stickerBitmap, 0); entity.currentFrame += entity.framesPerDraw; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index e93452e5e..b45b6297e 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -227,6 +227,10 @@ public class ConnectionsManager extends BaseController { return native_getCurrentTime(currentAccount); } + public int getCurrentDatacenterId() { + return native_getCurrentDatacenterId(currentAccount); + } + public int getTimeDifference() { return native_getTimeDifference(currentAccount); } @@ -513,6 +517,9 @@ public class ConnectionsManager extends BaseController { int flags = 0; EmuDetector detector = EmuDetector.with(ApplicationLoader.applicationContext); if (detector.detect()) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("detected emu"); + } flags |= 1024; } return flags; @@ -657,6 +664,7 @@ public class ConnectionsManager extends BaseController { public static native void native_resumeNetwork(int currentAccount, boolean partial); public static native long native_getCurrentTimeMillis(int currentAccount); public static native int native_getCurrentTime(int currentAccount); + public static native int native_getCurrentDatacenterId(int currentAccount); public static native int native_getTimeDifference(int currentAccount); public static native void native_sendRequest(int currentAccount, long object, RequestDelegateInternal onComplete, QuickAckDelegate onQuickAck, WriteToSocketDelegate onWriteToSocket, int flags, int datacenterId, int connetionType, boolean immediate, int requestToken); public static native void native_cancelRequest(int currentAccount, int token, boolean notifyServer); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 0352bb6b4..731f6d246 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -61,7 +61,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_EDITED = 0x00008000; public static final int MESSAGE_FLAG_MEGAGROUP = 0x80000000; - public static final int LAYER = 119; + public static final int LAYER = 120; public static class TL_stats_megagroupStats extends TLObject { public static int constructor = 0xef7ff916; @@ -2427,19 +2427,20 @@ public class TLRPC { public int pts; public int count; public int next_rate; + public int offset_id_offset; public static messages_Messages TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { messages_Messages result = null; switch (constructor) { + case 0x3a54685e: + result = new TL_messages_messagesSlice(); + break; case 0x8c718e87: result = new TL_messages_messages(); break; - case 0x99262e37: + case 0x64479808: result = new TL_messages_channelMessages(); break; - case 0xc8edce1e: - result = new TL_messages_messagesSlice(); - break; case 0x74535f21: result = new TL_messages_messagesNotModified(); break; @@ -2454,6 +2455,99 @@ public class TLRPC { } } + public static class TL_messages_messagesSlice extends messages_Messages { + public static int constructor = 0x3a54685e; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + inexact = (flags & 2) != 0; + count = stream.readInt32(exception); + if ((flags & 1) != 0) { + next_rate = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + offset_id_offset = stream.readInt32(exception); + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = inexact ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt32(count); + if ((flags & 1) != 0) { + stream.writeInt32(next_rate); + } + if ((flags & 4) != 0) { + stream.writeInt32(offset_id_offset); + } + stream.writeInt32(0x1cb5c415); + int count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + messages.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + public static class TL_messages_messages extends messages_Messages { public static int constructor = 0x8c718e87; @@ -2530,7 +2624,7 @@ public class TLRPC { } public static class TL_messages_channelMessages extends messages_Messages { - public static int constructor = 0x99262e37; + public static int constructor = 0x64479808; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2538,6 +2632,9 @@ public class TLRPC { inexact = (flags & 2) != 0; pts = stream.readInt32(exception); count = stream.readInt32(exception); + if ((flags & 4) != 0) { + offset_id_offset = stream.readInt32(exception); + } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -2591,92 +2688,8 @@ public class TLRPC { stream.writeInt32(flags); stream.writeInt32(pts); stream.writeInt32(count); - stream.writeInt32(0x1cb5c415); - int count = messages.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - messages.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static class TL_messages_messagesSlice extends messages_Messages { - public static int constructor = 0xc8edce1e; - - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - inexact = (flags & 2) != 0; - count = stream.readInt32(exception); - if ((flags & 1) != 0) { - next_rate = stream.readInt32(exception); - } - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - messages.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = inexact ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - stream.writeInt32(count); - if ((flags & 1) != 0) { - stream.writeInt32(next_rate); + if ((flags & 4) != 0) { + stream.writeInt32(offset_id_offset); } stream.writeInt32(0x1cb5c415); int count = messages.size(); @@ -4350,15 +4363,17 @@ public class TLRPC { } public static abstract class GeoPoint extends TLObject { - public double _long; - public double lat; + public int flags; + public double _long; + public double lat; + public int accuracy_radius; public long access_hash; public static GeoPoint TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { GeoPoint result = null; switch (constructor) { case 0x296f104: - result = new TL_geoPoint(); + result = new TL_geoPoint_layer119(); break; case 0x2049d70c: result = new TL_geoPoint_layer81(); @@ -4366,6 +4381,9 @@ public class TLRPC { case 0x1117dd5f: result = new TL_geoPointEmpty(); break; + case 0xb2a2f663: + result = new TL_geoPoint(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in GeoPoint", constructor)); @@ -4377,7 +4395,7 @@ public class TLRPC { } } - public static class TL_geoPoint extends GeoPoint { + public static class TL_geoPoint_layer119 extends TL_geoPoint { public static int constructor = 0x296f104; @@ -4420,6 +4438,32 @@ public class TLRPC { } } + public static class TL_geoPoint extends GeoPoint { + public static int constructor = 0xb2a2f663; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + _long = stream.readDouble(exception); + lat = stream.readDouble(exception); + access_hash = stream.readInt64(exception); + if ((flags & 1) != 0) { + accuracy_radius = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeDouble(_long); + stream.writeDouble(lat); + stream.writeInt64(access_hash); + if ((flags & 1) != 0) { + stream.writeInt32(accuracy_radius); + } + } + } + public static class TL_account_privacyRules extends TLObject { public static int constructor = 0x50a04e45; @@ -6350,7 +6394,37 @@ public class TLRPC { } } - public static class TL_messageMediaGeoLive extends MessageMedia { + public static class TL_messageMediaGeoLive extends MessageMedia { + public static int constructor = 0xb940c666; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + heading = stream.readInt32(exception); + } + period = stream.readInt32(exception); + if ((flags & 2) != 0) { + proximity_notification_radius = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + geo.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(heading); + } + stream.writeInt32(period); + if ((flags & 2) != 0) { + stream.writeInt32(proximity_notification_radius); + } + } + } + + public static class TL_messageMediaGeoLive_layer119 extends TL_messageMediaGeoLive { public static int constructor = 0x7c3c2609; @@ -7571,15 +7645,18 @@ public class TLRPC { } public static abstract class InputGeoPoint extends TLObject { - public double lat; - public double _long; + + public int flags; + public double lat; + public double _long; + public int accuracy_radius; public static InputGeoPoint TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputGeoPoint result = null; switch (constructor) { - case 0xf3b7acc9: - result = new TL_inputGeoPoint(); - break; + case 0x48222faf: + result = new TL_inputGeoPoint(); + break; case 0xe4c123d6: result = new TL_inputGeoPointEmpty(); break; @@ -7594,21 +7671,29 @@ public class TLRPC { } } - public static class TL_inputGeoPoint extends InputGeoPoint { - public static int constructor = 0xf3b7acc9; + public static class TL_inputGeoPoint extends InputGeoPoint { + public static int constructor = 0x48222faf; - public void readParams(AbstractSerializedData stream, boolean exception) { - lat = stream.readDouble(exception); - _long = stream.readDouble(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + lat = stream.readDouble(exception); + _long = stream.readDouble(exception); + if ((flags & 1) != 0) { + accuracy_radius = stream.readInt32(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeDouble(lat); - stream.writeDouble(_long); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeDouble(lat); + stream.writeDouble(_long); + if ((flags & 1) != 0) { + stream.writeInt32(accuracy_radius); + } + } + } public static class TL_inputGeoPointEmpty extends InputGeoPoint { public static int constructor = 0xe4c123d6; @@ -12201,6 +12286,8 @@ public class TLRPC { public String vcard; public boolean no_webpage; public int period; + public int heading; + public int proximity_notification_radius; public static BotInlineMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { BotInlineMessage result = null; @@ -12230,8 +12317,11 @@ public class TLRPC { result = new TL_botInlineMessageText(); break; case 0xb722de65: - result = new TL_botInlineMessageMediaGeo(); + result = new TL_botInlineMessageMediaGeo_layer119(); break; + case 0x51846fd: + result = new TL_botInlineMessageMediaGeo(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in BotInlineMessage", constructor)); @@ -12497,7 +12587,47 @@ public class TLRPC { } } - public static class TL_botInlineMessageMediaGeo extends BotInlineMessage { + public static class TL_botInlineMessageMediaGeo extends BotInlineMessage { + public static int constructor = 0x51846fd; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + heading = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + period = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + proximity_notification_radius = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + geo.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(heading); + } + if ((flags & 2) != 0) { + stream.writeInt32(period); + } + if ((flags & 8) != 0) { + stream.writeInt32(proximity_notification_radius); + } + if ((flags & 4) != 0) { + reply_markup.serializeToStream(stream); + } + } + } + + public static class TL_botInlineMessageMediaGeo_layer119 extends TL_botInlineMessageMediaGeo { public static int constructor = 0xb722de65; @@ -16173,6 +16303,9 @@ public class TLRPC { public static ChannelParticipantsFilter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChannelParticipantsFilter result = null; switch (constructor) { + case 0xe04b5ceb: + result = new TL_channelParticipantsMentions(); + break; case 0xbb6ae88d: result = new TL_channelParticipantsContacts(); break; @@ -16205,6 +16338,34 @@ public class TLRPC { } } + public static class TL_channelParticipantsMentions extends ChannelParticipantsFilter { + public static int constructor = 0xe04b5ceb; + + public int flags; + public int top_msg_id; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + q = stream.readString(exception); + } + if ((flags & 2) != 0) { + top_msg_id = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(q); + } + if ((flags & 2) != 0) { + stream.writeInt32(top_msg_id); + } + } + } + public static class TL_channelParticipantsContacts extends ChannelParticipantsFilter { public static int constructor = 0xbb6ae88d; @@ -16381,6 +16542,9 @@ public class TLRPC { case 0x94bd38ed: result = new TL_messageActionPinMessage(); break; + case 0x98e0d697: + result = new TL_messageActionGeoProximityReached(); + break; case 0x95e3fbef: result = new TL_messageActionChatDeletePhoto(); break; @@ -16755,6 +16919,27 @@ public class TLRPC { } } + public static class TL_messageActionGeoProximityReached extends MessageAction { + public static int constructor = 0x98e0d697; + + public Peer from_id; + public Peer to_id; + public int distance; + + public void readParams(AbstractSerializedData stream, boolean exception) { + from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + to_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + distance = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + from_id.serializeToStream(stream); + to_id.serializeToStream(stream); + stream.writeInt32(distance); + } + } + public static class TL_messageActionChatDeletePhoto extends MessageAction { public static int constructor = 0x95e3fbef; @@ -20531,6 +20716,7 @@ public class TLRPC { public String provider; public String venue_id; public String venue_type; + public int heading; public int period; public boolean nosound_video; public boolean force_file; @@ -20538,6 +20724,7 @@ public class TLRPC { public InputFile thumb; public String mime_type; public ArrayList attributes = new ArrayList<>(); + public int proximity_notification_radius; public static InputMedia TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputMedia result = null; @@ -20572,7 +20759,7 @@ public class TLRPC { case 0xc13d1c11: result = new TL_inputMediaVenue(); break; - case 0xce4e82fd: + case 0x971fa843: result = new TL_inputMediaGeoLive(); break; case 0x5b38c6c1: @@ -20857,16 +21044,22 @@ public class TLRPC { } public static class TL_inputMediaGeoLive extends InputMedia { - public static int constructor = 0xce4e82fd; + public static int constructor = 0x971fa843; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); stopped = (flags & 1) != 0; geo_point = InputGeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + heading = stream.readInt32(exception); + } if ((flags & 2) != 0) { period = stream.readInt32(exception); } + if ((flags & 8) != 0) { + proximity_notification_radius = stream.readInt32(exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -20874,9 +21067,15 @@ public class TLRPC { flags = stopped ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); geo_point.serializeToStream(stream); + if ((flags & 4) != 0) { + stream.writeInt32(heading); + } if ((flags & 2) != 0) { stream.writeInt32(period); } + if ((flags & 8) != 0) { + stream.writeInt32(proximity_notification_radius); + } } } @@ -21725,12 +21924,12 @@ public class TLRPC { case 0xaca1657b: result = new TL_updateMessagePoll(); break; - case 0x4c43da18: - result = new TL_updateUserPinnedMessage(); - break; case 0xa20db0e5: result = new TL_updateDeleteMessages(); break; + case 0x8588878b: + result = new TL_updatePinnedChannelMessages(); + break; case 0x571d2742: result = new TL_updateReadFeaturedStickers(); break; @@ -21794,9 +21993,6 @@ public class TLRPC { case 0x6e5f8c22: result = new TL_updateChatParticipantDelete(); break; - case 0xe10db349: - result = new TL_updateChatPinnedMessage(); - break; case 0xe40370a3: result = new TL_updateEditMessage(); break; @@ -21833,9 +22029,6 @@ public class TLRPC { case 0xebe46819: result = new TL_updateServiceNotification(); break; - case 0x98592475: - result = new TL_updateChannelPinnedMessage(); - break; case 0x56022f4d: result = new TL_updateLangPack(); break; @@ -21926,6 +22119,9 @@ public class TLRPC { case 0x246a4b22: result = new TL_updatePeerBlocked(); break; + case 0xed85eab5: + result = new TL_updatePinnedMessages(); + break; case 0x8e5e9873: result = new TL_updateDcOptions(); break; @@ -21970,24 +22166,6 @@ public class TLRPC { } } - public static class TL_updateUserPinnedMessage extends Update { - public static int constructor = 0x4c43da18; - - public int user_id; - public int id; - - public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); - id = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(user_id); - stream.writeInt32(id); - } - } - public static class TL_updateDeleteMessages extends Update { public static int constructor = 0xa20db0e5; @@ -22024,6 +22202,51 @@ public class TLRPC { } } + public static class TL_updatePinnedChannelMessages extends Update { + public static int constructor = 0x8588878b; + + public int flags; + public boolean pinned; + public int channel_id; + public ArrayList messages = new ArrayList<>(); + public int pts; + public int pts_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 1) != 0; + channel_id = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + messages.add(stream.readInt32(exception)); + } + pts = stream.readInt32(exception); + pts_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(channel_id); + stream.writeInt32(0x1cb5c415); + int count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(messages.get(a)); + } + stream.writeInt32(pts); + stream.writeInt32(pts_count); + } + } + public static class TL_updateReadFeaturedStickers extends Update { public static int constructor = 0x571d2742; @@ -22451,27 +22674,6 @@ public class TLRPC { } } - public static class TL_updateChatPinnedMessage extends Update { - public static int constructor = 0xe10db349; - - public int chat_id; - public int id; - public int version; - - public void readParams(AbstractSerializedData stream, boolean exception) { - chat_id = stream.readInt32(exception); - id = stream.readInt32(exception); - version = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(chat_id); - stream.writeInt32(id); - stream.writeInt32(version); - } - } - public static class TL_updateEditMessage extends Update { public static int constructor = 0xe40370a3; @@ -22774,24 +22976,6 @@ public class TLRPC { } } - public static class TL_updateChannelPinnedMessage extends Update { - public static int constructor = 0x98592475; - - public int channel_id; - public int id; - - public void readParams(AbstractSerializedData stream, boolean exception) { - channel_id = stream.readInt32(exception); - id = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(channel_id); - stream.writeInt32(id); - } - } - public static class TL_updateLangPack extends Update { public static int constructor = 0x56022f4d; @@ -23485,6 +23669,51 @@ public class TLRPC { } } + public static class TL_updatePinnedMessages extends Update { + public static int constructor = 0xed85eab5; + + public int flags; + public boolean pinned; + public Peer peer; + public ArrayList messages = new ArrayList<>(); + public int pts; + public int pts_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 1) != 0; + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + messages.add(stream.readInt32(exception)); + } + pts = stream.readInt32(exception); + pts_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(messages.get(a)); + } + stream.writeInt32(pts); + stream.writeInt32(pts_count); + } + } + public static class TL_updateDcOptions extends Update { public static int constructor = 0x8e5e9873; @@ -28237,6 +28466,9 @@ public class TLRPC { switch (constructor) { case 0x1c0facaf: result = new TL_channelParticipantBanned(); + break; + case 0xc3c6796b: + result = new TL_channelParticipantLeft(); break; case 0x222c1886: result = new TL_channelParticipantBanned_layer92(); @@ -28309,6 +28541,20 @@ public class TLRPC { } } + public static class TL_channelParticipantLeft extends ChannelParticipant { + public static int constructor = 0xc3c6796b; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + user_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(user_id); + } + } + public static class TL_channelParticipantCreator_layer103 extends TL_channelParticipantCreator { public static int constructor = 0xe3e2e1f9; @@ -32266,6 +32512,9 @@ public class TLRPC { case 0xe7026d0d: result = new TL_inputMessagesFilterGeo(); break; + case 0x1bb00451: + result = new TL_inputMessagesFilterPinned(); + break; case 0xc1f8e69a: result = new TL_inputMessagesFilterMyMentions(); break; @@ -32382,6 +32631,15 @@ public class TLRPC { } } + public static class TL_inputMessagesFilterPinned extends MessagesFilter { + public static int constructor = 0x1bb00451; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_inputMessagesFilterMyMentions extends MessagesFilter { public static int constructor = 0xc1f8e69a; @@ -36865,12 +37123,12 @@ public class TLRPC { } public static class TL_messages_search extends TLObject { - public static int constructor = 0x4e17810b; + public static int constructor = 0xc352eec; public int flags; public InputPeer peer; public String q; - public InputUser from_id; + public InputPeer from_id; public int top_msg_id; public MessagesFilter filter; public int min_date; @@ -40262,6 +40520,8 @@ public class TLRPC { public int flags; public boolean silent; + public boolean unpin; + public boolean pm_oneside; public InputPeer peer; public int id; @@ -40272,6 +40532,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = silent ? (flags | 1) : (flags &~ 1); + flags = unpin ? (flags | 2) : (flags &~ 2); + flags = pm_oneside ? (flags | 4) : (flags &~ 4); stream.writeInt32(flags); peer.serializeToStream(stream); stream.writeInt32(id); @@ -40938,6 +41200,21 @@ public class TLRPC { } } + public static class TL_messages_unpinAllMessages extends TLObject { + public static int constructor = 0xf025bc8b; + + public InputPeer peer; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_affectedHistory.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } + public static class TL_help_getAppChangelog extends TLObject { public static int constructor = 0x9010ef6f; @@ -42736,6 +43013,7 @@ public class TLRPC { public boolean shipping_address_requested; public Photo photo; public GeoPoint geo; + public int heading; public String currency; public String description; public int receipt_msg_id; @@ -42759,6 +43037,7 @@ public class TLRPC { public boolean test; public int period; public int ttl_seconds; + public int proximity_notification_radius; public static MessageMedia TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageMedia result = null; @@ -42784,8 +43063,11 @@ public class TLRPC { case 0x7912b71f: result = new TL_messageMediaVenue_layer71(); break; + case 0xb940c666: + result = new TL_messageMediaGeoLive(); + break; case 0x7c3c2609: - result = new TL_messageMediaGeoLive(); + result = new TL_messageMediaGeoLive_layer119(); break; case 0x2ec0533f: result = new TL_messageMediaVenue(); @@ -43259,6 +43541,7 @@ public class TLRPC { public boolean from_scheduled; public boolean legacy; public boolean edit_hide; + public boolean pinned; public MessageFwdHeader fwd_from; public int via_bot_id; public TL_messageReplyHeader reply_to; @@ -44039,6 +44322,7 @@ public class TLRPC { from_scheduled = (flags & 262144) != 0; legacy = (flags & 524288) != 0; edit_hide = (flags & 2097152) != 0; + pinned = (flags & 16777216) != 0; id = stream.readInt32(exception); if ((flags & 256) != 0) { from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -44131,6 +44415,7 @@ public class TLRPC { flags = from_scheduled ? (flags | 262144) : (flags &~ 262144); flags = legacy ? (flags | 524288) : (flags &~ 524288); flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152); + flags = pinned ? (flags | 16777216) : (flags &~ 16777216); stream.writeInt32(flags); stream.writeInt32(id); if ((flags & 256) != 0) { 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 967f80d33..0281a1cb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -948,9 +948,16 @@ public class ActionBarLayout extends FrameLayout { layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = LayoutHelper.MATCH_PARENT; if (preview) { + int height = fragment.getPreviewHeight(); + int statusBarHeight = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); + if (height > 0 && height < getMeasuredHeight() - statusBarHeight) { + layoutParams.height = height; + layoutParams.topMargin = statusBarHeight + (getMeasuredHeight() - statusBarHeight - height) / 2; + } else { + layoutParams.topMargin = layoutParams.bottomMargin = AndroidUtilities.dp(46); + layoutParams.topMargin += AndroidUtilities.statusBarHeight; + } layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(8); - layoutParams.topMargin = layoutParams.bottomMargin = AndroidUtilities.dp(46); - layoutParams.topMargin += AndroidUtilities.statusBarHeight; } else { layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; } @@ -1183,6 +1190,7 @@ public class ActionBarLayout extends FrameLayout { fragment.setParentLayout(null); fragmentsStack.remove(fragment); containerViewBack.setVisibility(View.INVISIBLE); + containerViewBack.setTranslationY(0); bringChildToFront(containerView); } @@ -1208,6 +1216,7 @@ public class ActionBarLayout extends FrameLayout { } FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.fragmentView.getLayoutParams(); layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; + layoutParams.height = LayoutHelper.MATCH_PARENT; fragment.fragmentView.setLayoutParams(layoutParams); presentFragmentInternalRemoveOld(false, prevFragment); 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 459c8bbf6..964b5a9f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -704,20 +704,21 @@ public class ActionBarMenuItem extends FrameLayout { }.setDuration(150)).addTransition(changeBounds); transition.setOrdering(TransitionSet.ORDERING_TOGETHER); transition.setInterpolator(CubicBezierInterpolator.EASE_OUT); + int selectedAccount = UserConfig.selectedAccount; transition.addListener(new Transition.TransitionListener() { @Override public void onTransitionStart(Transition transition) { - notificationIndex = NotificationCenter.getInstance(UserConfig.selectedAccount).setAnimationInProgress(notificationIndex,null); + notificationIndex = NotificationCenter.getInstance(selectedAccount).setAnimationInProgress(notificationIndex,null); } @Override public void onTransitionEnd(Transition transition) { - NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(notificationIndex); + NotificationCenter.getInstance(selectedAccount).onAnimationFinish(notificationIndex); } @Override public void onTransitionCancel(Transition transition) { - NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(notificationIndex); + NotificationCenter.getInstance(selectedAccount).onAnimationFinish(notificationIndex); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 510c6da47..207e0b021 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -34,7 +34,9 @@ import android.widget.ScrollView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.ui.Components.LayoutHelper; import java.lang.reflect.Field; @@ -51,6 +53,10 @@ public class ActionBarPopupWindow extends PopupWindow { private AnimatorSet windowAnimatorSet; private boolean animationEnabled = allowAnimation; private int dismissAnimationDuration = 150; + private boolean isClosingAnimated; + private int currentAccount = UserConfig.selectedAccount; + private boolean pauseNotifications; + static { Field f = null; try { @@ -68,6 +74,7 @@ public class ActionBarPopupWindow extends PopupWindow { private ViewTreeObserver.OnScrollChangedListener mSuperScrollListener; private ViewTreeObserver mViewTreeObserver; + private int popupAnimationIndex = -1; public interface OnDispatchKeyEventListener { void onDispatchKeyEvent(KeyEvent keyEvent); @@ -426,12 +433,7 @@ public class ActionBarPopupWindow extends PopupWindow { ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, 1.0f), ObjectAnimator.ofInt(content, "backAlpha", 0, 255)); windowAnimatorSet.setDuration(150 + 16 * visibleCount); - windowAnimatorSet.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - + windowAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { windowAnimatorSet = null; @@ -442,16 +444,6 @@ public class ActionBarPopupWindow extends PopupWindow { child.setAlpha(1.0f); } } - - @Override - public void onAnimationCancel(Animator animation) { - onAnimationEnd(animation); - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } }); windowAnimatorSet.start(); } @@ -480,12 +472,22 @@ public class ActionBarPopupWindow extends PopupWindow { dismiss(true); } + public void setPauseNotifications(boolean value) { + pauseNotifications = value; + } + public void dismiss(boolean animated) { setFocusable(false); - if (animationEnabled && animated) { - if (windowAnimatorSet != null) { - windowAnimatorSet.cancel(); + if (windowAnimatorSet != null) { + if (animated && isClosingAnimated) { + return; } + windowAnimatorSet.cancel(); + windowAnimatorSet = null; + } + isClosingAnimated = false; + if (animationEnabled && animated) { + isClosingAnimated = true; ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView(); if (content.itemAnimators != null && !content.itemAnimators.isEmpty()) { for (int a = 0, N = content.itemAnimators.size(); a < N; a++) { @@ -500,15 +502,11 @@ public class ActionBarPopupWindow extends PopupWindow { ObjectAnimator.ofFloat(content, View.TRANSLATION_Y, AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)), ObjectAnimator.ofFloat(content, View.ALPHA, 0.0f)); windowAnimatorSet.setDuration(dismissAnimationDuration); - windowAnimatorSet.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - + windowAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { windowAnimatorSet = null; + isClosingAnimated = false; setFocusable(false); try { ActionBarPopupWindow.super.dismiss(); @@ -516,18 +514,14 @@ public class ActionBarPopupWindow extends PopupWindow { } unregisterListener(); - } - - @Override - public void onAnimationCancel(Animator animation) { - onAnimationEnd(animation); - } - - @Override - public void onAnimationRepeat(Animator animation) { - + if (pauseNotifications) { + NotificationCenter.getInstance(currentAccount).onAnimationFinish(popupAnimationIndex); + } } }); + if (pauseNotifications) { + popupAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(popupAnimationIndex, null); + } windowAnimatorSet.start(); } else { try { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java index d6ea991b3..6079f4543 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java @@ -13,8 +13,6 @@ import android.view.Window; import android.view.animation.Interpolator; import android.widget.FrameLayout; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SharedConfig; @@ -127,11 +125,12 @@ public class AdjustPanLayoutHelper { onPanTranslationUpdate(-y, v, isKeyboardVisible); }); animationInProgress = true; + int selectedAccount = UserConfig.selectedAccount; animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animationInProgress = false; - NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(notificationsIndex); + NotificationCenter.getInstance(selectedAccount).onAnimationFinish(notificationsIndex); animator = null; setViewHeight(ViewGroup.LayoutParams.MATCH_PARENT); viewsToHeightSet.clear(); @@ -144,7 +143,7 @@ public class AdjustPanLayoutHelper { animator.setDuration(220); animator.setInterpolator(CubicBezierInterpolator.DEFAULT); - notificationsIndex = NotificationCenter.getInstance(UserConfig.selectedAccount).setAnimationInProgress(notificationsIndex, null); + notificationsIndex = NotificationCenter.getInstance(selectedAccount).setAnimationInProgress(notificationsIndex, null); animator.start(); } 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 434dafb64..26b9d59c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -83,6 +83,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { private CharSequence subtitle; private CharSequence message; private int topResId; + private View topView; private int topAnimationId; private int topHeight = 132; private Drawable topDrawable; @@ -270,6 +271,14 @@ public class AlertDialog extends Dialog implements Drawable.Callback { topImageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(topHeight), MeasureSpec.EXACTLY)); availableHeight -= topImageView.getMeasuredHeight() - AndroidUtilities.dp(8); } + if (topView != null) { + int w = width - AndroidUtilities.dp(16); + float scale = w / 936.0f; + int h = (int) (354 * scale); + topView.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); + topView.getLayoutParams().height = h; + availableHeight -= topView.getMeasuredHeight(); + } if (progressViewStyle == 0) { layoutParams = (LayoutParams) contentScrollView.getLayoutParams(); @@ -398,6 +407,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback { topImageView.getBackground().setColorFilter(new PorterDuffColorFilter(topBackgroundColor, PorterDuff.Mode.MULTIPLY)); topImageView.setPadding(0, 0, 0, 0); containerView.addView(topImageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, topHeight, Gravity.LEFT | Gravity.TOP, -8, -8, 0, 0)); + } else if (topView != null) { + topView.setPadding(0, 0, 0, 0); + containerView.addView(topView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, topHeight, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); } if (title != null) { @@ -1102,6 +1114,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback { return this; } + public Builder setTopView(View view) { + alertDialog.topView = view; + return this; + } + public Builder setTopAnimation(int resId, int backgroundColor) { alertDialog.topAnimationId = resId; alertDialog.topBackgroundColor = backgroundColor; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 837ca2987..dec14abd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -42,6 +42,7 @@ import org.telegram.messenger.SecretChatHelper; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.ui.Components.LayoutHelper; import java.util.ArrayList; @@ -429,6 +430,10 @@ public class BaseFragment { } } + protected int getPreviewHeight() { + return LayoutHelper.MATCH_PARENT; + } + protected void onBecomeFullyHidden() { } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index 869856c45..ba57c7b1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -52,7 +52,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.FileLog; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -521,9 +520,6 @@ public class BottomSheet extends Dialog { float translation = 0; if (Build.VERSION.SDK_INT >= 29 && getAdditionalMandatoryOffsets() > 0) { float dist = containerView.getMeasuredHeight() - containerView.getTranslationY(); - if (currentSheetAnimationType == 1) { - dist *= 0.1f; - } translation = Math.max(0, bottomInset - dist); } int navBarHeight = drawNavigationBar ? bottomInset : 0; @@ -678,11 +674,6 @@ public class BottomSheet extends Dialog { } } - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - } - public void setAllowNestedScroll(boolean value) { allowNestedScroll = value; if (!allowNestedScroll) { @@ -1247,6 +1238,10 @@ public class BottomSheet extends Dialog { return this; } + public View getCustomView() { + return bottomSheet.customView; + } + public Builder setTitle(CharSequence title) { return setTitle(title, false); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java index bee51da2f..291b67a4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -164,7 +164,7 @@ public class SimpleTextView extends View implements Drawable.Callback { } } - private boolean createLayout(int width) { + protected boolean createLayout(int width) { if (text != null) { try { if (leftDrawable != null) { 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 f248c80b3..39a83f631 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -83,11 +83,18 @@ import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.AudioVisualizerDrawable; import org.telegram.ui.Components.BackgroundGradientDrawable; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.MsgClockDrawable; import org.telegram.ui.Components.PathAnimator; +import org.telegram.ui.Components.PlayingGameDrawable; import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.Components.RecordStatusDrawable; +import org.telegram.ui.Components.RoundStatusDrawable; import org.telegram.ui.Components.ScamDrawable; +import org.telegram.ui.Components.SendingFileDrawable; +import org.telegram.ui.Components.StatusDrawable; import org.telegram.ui.Components.SvgHelper; import org.telegram.ui.Components.ThemeEditorView; +import org.telegram.ui.Components.TypingDotsDrawable; import java.io.File; import java.io.FileInputStream; @@ -106,6 +113,7 @@ import java.util.HashSet; import java.util.Locale; import androidx.annotation.UiThread; +import androidx.core.graphics.ColorUtils; public class Theme { @@ -220,6 +228,10 @@ public class Theme { isBottomNear = bottomNear; } + public int getTopY() { + return topY; + } + private int dp(float value) { if (currentType == TYPE_PREVIEW) { return (int) Math.ceil(3 * value); @@ -479,7 +491,7 @@ public class Theme { } } if (currentType == TYPE_MEDIA) { - if (currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { + if (paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { int radToUse = isBottomNear ? nearRad : rad; path.lineTo(bounds.right - padding, bounds.bottom - padding - radToUse); @@ -534,7 +546,7 @@ public class Theme { } } if (currentType == TYPE_MEDIA) { - if (currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { + if (paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { int radToUse = isBottomNear ? nearRad : rad; path.lineTo(bounds.left + padding, bounds.bottom - padding - radToUse); @@ -556,8 +568,9 @@ public class Theme { path.close(); canvas.drawPath(path, p); - if (gradientShader != null && isSelected) { - selectedPaint.setColor(getColor(key_chat_outBubbleGradientSelectedOverlay)); + if (gradientShader != null && isSelected && paintToUse == null) { + int color = getColor(key_chat_outBubbleGradientSelectedOverlay); + selectedPaint.setColor(ColorUtils.setAlphaComponent(color, (int) (Color.alpha(color) * alpha / 255f))); canvas.drawPath(path, selectedPaint); } } @@ -975,7 +988,7 @@ public class Theme { int subTextColor; int seekbarColor; if (useBlackText(myMessagesAccentColor, myMessagesGradientAccentColor)) { - textColor = 0xff000000; + textColor = 0xff212121; subTextColor = 0xff555555; seekbarColor = 0x4d000000; } else { @@ -1010,6 +1023,7 @@ public class Theme { currentColors.put(key_chat_outPreviewInstantSelectedText, textColor); currentColors.put(key_chat_outViews, textColor); + currentColors.put(key_chat_outViewsSelected, textColor); currentColors.put(key_chat_outAudioTitleText, textColor); currentColors.put(key_chat_outFileNameText, textColor); @@ -1976,6 +1990,7 @@ public class Theme { public static Paint dialogs_countPaint; public static Paint dialogs_errorPaint; public static Paint dialogs_countGrayPaint; + public static Paint dialogs_actionMessagePaint; public static TextPaint[] dialogs_namePaint; public static TextPaint[] dialogs_nameEncryptedPaint; public static TextPaint dialogs_searchNamePaint; @@ -2083,6 +2098,7 @@ public class Theme { public static MessageDrawable chat_msgInMediaSelectedDrawable; public static MessageDrawable chat_msgOutMediaDrawable; public static MessageDrawable chat_msgOutMediaSelectedDrawable; + private static StatusDrawable[] chat_status_drawables = new StatusDrawable[5]; public static PathAnimator playPauseAnimator; public static Drawable chat_msgOutCheckDrawable; @@ -2111,6 +2127,12 @@ public class Theme { public static Drawable chat_msgInRepliesSelectedDrawable; public static Drawable chat_msgOutRepliesDrawable; public static Drawable chat_msgOutRepliesSelectedDrawable; + public static Drawable chat_msgInPinnedDrawable; + public static Drawable chat_msgInPinnedSelectedDrawable; + public static Drawable chat_msgOutPinnedDrawable; + public static Drawable chat_msgOutPinnedSelectedDrawable; + public static Drawable chat_msgStickerPinnedDrawable; + public static Drawable chat_msgMediaPinnedDrawable; public static Drawable chat_msgMediaViewsDrawable; public static Drawable chat_msgMediaRepliesDrawable; public static Drawable chat_msgInMenuDrawable; @@ -3425,10 +3447,10 @@ public class Theme { defaultColors.put(key_chat_messagePanelVoiceDuration, 0xffffffff); defaultColors.put(key_chat_inlineResultIcon, 0xff5795cc); defaultColors.put(key_chat_topPanelBackground, 0xffffffff); - defaultColors.put(key_chat_topPanelClose, 0xff8c959a); + defaultColors.put(key_chat_topPanelClose, 0xff8b969b); defaultColors.put(key_chat_topPanelLine, 0xff6c9fd2); defaultColors.put(key_chat_topPanelTitle, 0xff3a8ccf); - defaultColors.put(key_chat_topPanelMessage, 0xff999999); + defaultColors.put(key_chat_topPanelMessage, 0xff878e91); defaultColors.put(key_chat_reportSpam, 0xffcf5957); defaultColors.put(key_chat_addContact, 0xff4a82b5); defaultColors.put(key_chat_inLoader, 0xff72b5e8); @@ -3522,7 +3544,7 @@ public class Theme { defaultColors.put(key_inappPlayerTitle, 0xff2f3438); defaultColors.put(key_inappPlayerBackground, 0xffffffff); defaultColors.put(key_inappPlayerPlayPause, 0xff62b0eb); - defaultColors.put(key_inappPlayerClose, 0xffa8a8a8); + defaultColors.put(key_inappPlayerClose, 0xff8b969b); defaultColors.put(key_returnToCallBackground, 0xff44a1e3); defaultColors.put(key_returnToCallText, 0xffffffff); @@ -4373,6 +4395,8 @@ public class Theme { eventType = 0; } else if (monthOfYear == 1 && dayOfMonth == 14) { eventType = 1; + } else if (monthOfYear == 9 && dayOfMonth >= 30 || monthOfYear == 10 && dayOfMonth == 1 && hour < 12) { + eventType = 2; } return eventType; } @@ -6621,13 +6645,14 @@ public class Theme { dialogs_countPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_countGrayPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_errorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + dialogs_actionMessagePaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_lockDrawable = resources.getDrawable(R.drawable.list_secret); dialogs_checkDrawable = resources.getDrawable(R.drawable.list_check).mutate(); dialogs_playDrawable = resources.getDrawable(R.drawable.minithumb_play).mutate(); dialogs_checkReadDrawable = resources.getDrawable(R.drawable.list_check).mutate(); dialogs_halfCheckDrawable = resources.getDrawable(R.drawable.list_halfcheck); - dialogs_clockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); + dialogs_clockDrawable = new MsgClockDrawable(); dialogs_errorDrawable = resources.getDrawable(R.drawable.list_warning_sign); dialogs_reorderDrawable = resources.getDrawable(R.drawable.list_reorder).mutate(); dialogs_groupDrawable = resources.getDrawable(R.drawable.list_group); @@ -6674,6 +6699,7 @@ public class Theme { dialogs_archiveTextPaint.setColor(getColor(key_chats_archiveText)); dialogs_countPaint.setColor(getColor(key_chats_unreadCounter)); dialogs_countGrayPaint.setColor(getColor(key_chats_unreadCounterMuted)); + dialogs_actionMessagePaint.setColor(getColor(key_chats_actionMessage)); dialogs_errorPaint.setColor(getColor(key_chats_sentError)); dialogs_onlinePaint.setColor(getColor(key_windowBackgroundWhiteBlueText3)); dialogs_offlinePaint.setColor(getColor(key_windowBackgroundWhiteGrayText3)); @@ -6833,12 +6859,12 @@ public class Theme { chat_msgOutHalfCheckSelectedDrawable = resources.getDrawable(R.drawable.msg_halfcheck).mutate(); chat_msgMediaHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck_s).mutate(); chat_msgStickerHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck_s).mutate(); - chat_msgOutClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); - chat_msgOutSelectedClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); - chat_msgInClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); - chat_msgInSelectedClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); - chat_msgMediaClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); - chat_msgStickerClockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); + chat_msgOutClockDrawable = new MsgClockDrawable(); + chat_msgOutSelectedClockDrawable = new MsgClockDrawable(); + chat_msgInClockDrawable = new MsgClockDrawable(); + chat_msgInSelectedClockDrawable = new MsgClockDrawable(); + chat_msgMediaClockDrawable = new MsgClockDrawable(); + chat_msgStickerClockDrawable = new MsgClockDrawable(); chat_msgInViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate(); chat_msgInViewsSelectedDrawable = resources.getDrawable(R.drawable.msg_views).mutate(); chat_msgOutViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate(); @@ -6847,6 +6873,12 @@ public class Theme { chat_msgInRepliesSelectedDrawable = resources.getDrawable(R.drawable.msg_reply_small).mutate(); chat_msgOutRepliesDrawable = resources.getDrawable(R.drawable.msg_reply_small).mutate(); chat_msgOutRepliesSelectedDrawable = resources.getDrawable(R.drawable.msg_reply_small).mutate(); + chat_msgInPinnedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); + chat_msgInPinnedSelectedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); + chat_msgOutPinnedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); + chat_msgOutPinnedSelectedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); + chat_msgMediaPinnedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); + chat_msgStickerPinnedDrawable = resources.getDrawable(R.drawable.msg_pin_mini).mutate(); chat_msgMediaViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate(); chat_msgMediaRepliesDrawable = resources.getDrawable(R.drawable.msg_reply_small).mutate(); chat_msgStickerViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate(); @@ -7180,6 +7212,12 @@ public class Theme { setDrawableColorByKey(chat_msgInRepliesSelectedDrawable, key_chat_inViewsSelected); setDrawableColorByKey(chat_msgOutRepliesDrawable, key_chat_outViews); setDrawableColorByKey(chat_msgOutRepliesSelectedDrawable, key_chat_outViewsSelected); + setDrawableColorByKey(chat_msgInPinnedDrawable, key_chat_inViews); + setDrawableColorByKey(chat_msgInPinnedSelectedDrawable, key_chat_inViewsSelected); + setDrawableColorByKey(chat_msgOutPinnedDrawable, key_chat_outViews); + setDrawableColorByKey(chat_msgOutPinnedSelectedDrawable, key_chat_outViewsSelected); + setDrawableColorByKey(chat_msgMediaPinnedDrawable, key_chat_mediaViews); + setDrawableColorByKey(chat_msgStickerPinnedDrawable, key_chat_serviceText); setDrawableColorByKey(chat_msgMediaViewsDrawable, key_chat_mediaViews); setDrawableColorByKey(chat_msgMediaRepliesDrawable, key_chat_mediaViews); setDrawableColorByKey(chat_msgInMenuDrawable, key_chat_inMenu); @@ -7217,6 +7255,10 @@ public class Theme { setDrawableColorByKey(calllog_msgCallDownRedDrawable, key_calls_callReceivedRedIcon); setDrawableColorByKey(calllog_msgCallDownGreenDrawable, key_calls_callReceivedGreenIcon); + for (int i = 0; i < chat_status_drawables.length; i++) { + setDrawableColorByKey(chat_status_drawables[i], key_chats_actionMessage); + } + for (int a = 0; a < 2; a++) { setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][0], getColor(key_chat_outLoader), false); setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][0], getColor(key_chat_outMediaIcon), true); @@ -7595,7 +7637,9 @@ public class Theme { if (drawable == null) { return; } - if (drawable instanceof ShapeDrawable) { + if (drawable instanceof MsgClockDrawable) { + ((MsgClockDrawable) drawable).setColor(color); + } else if (drawable instanceof ShapeDrawable) { ((ShapeDrawable) drawable).getPaint().setColor(color); } else if (drawable instanceof ScamDrawable) { ((ScamDrawable) drawable).setColor(color); @@ -7614,20 +7658,16 @@ public class Theme { public static void setEmojiDrawableColor(Drawable drawable, int color, boolean selected) { if (drawable instanceof StateListDrawable) { try { + Drawable state; if (selected) { - Drawable state = getStateDrawable(drawable, 0); - if (state instanceof ShapeDrawable) { - ((ShapeDrawable) state).getPaint().setColor(color); - } else { - state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); - } + state = getStateDrawable(drawable, 0); } else { - Drawable state = getStateDrawable(drawable, 1); - if (state instanceof ShapeDrawable) { - ((ShapeDrawable) state).getPaint().setColor(color); - } else { - state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); - } + state = getStateDrawable(drawable, 1); + } + if (state instanceof ShapeDrawable) { + ((ShapeDrawable) state).getPaint().setColor(color); + } else { + state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } } catch (Throwable ignore) { @@ -7652,26 +7692,22 @@ public class Theme { public static void setSelectorDrawableColor(Drawable drawable, int color, boolean selected) { if (drawable instanceof StateListDrawable) { try { + Drawable state; if (selected) { - Drawable state = getStateDrawable(drawable, 0); + state = getStateDrawable(drawable, 0); if (state instanceof ShapeDrawable) { ((ShapeDrawable) state).getPaint().setColor(color); } else { state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } state = getStateDrawable(drawable, 1); - if (state instanceof ShapeDrawable) { - ((ShapeDrawable) state).getPaint().setColor(color); - } else { - state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); - } } else { - Drawable state = getStateDrawable(drawable, 2); - if (state instanceof ShapeDrawable) { - ((ShapeDrawable) state).getPaint().setColor(color); - } else { - state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); - } + state = getStateDrawable(drawable, 2); + } + if (state instanceof ShapeDrawable) { + ((ShapeDrawable) state).getPaint().setColor(color); + } else { + state.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } } catch (Throwable ignore) { @@ -8108,4 +8144,35 @@ public class Theme { } return animatedOutVisualizerDrawables.get(messageObject); } + + public static StatusDrawable getChatStatusDrawable(int type) { + if (type < 0 || type > 4) { + return null; + } + StatusDrawable statusDrawable = chat_status_drawables[type]; + if (statusDrawable != null) { + return statusDrawable; + } + switch (type) { + case 0: + chat_status_drawables[0] = new TypingDotsDrawable(true); + break; + case 1: + chat_status_drawables[1] = new RecordStatusDrawable(true); + break; + case 2: + chat_status_drawables[2] = new SendingFileDrawable(true); + break; + case 3: + chat_status_drawables[3] = new PlayingGameDrawable(true); + break; + case 4: + chat_status_drawables[4] = new RoundStatusDrawable(true); + break; + } + statusDrawable = chat_status_drawables[type]; + statusDrawable.start(); + statusDrawable.setColor(getColor(key_chats_actionMessage)); + return statusDrawable; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java index 41a59ed63..77db4b443 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java @@ -353,6 +353,10 @@ public class ThemeDescription { } } else if (viewToInvalidate instanceof ContextProgressView) { ((ContextProgressView) viewToInvalidate).updateColors(); + } else if (viewToInvalidate instanceof SeekBarView) { + if ((changeFlags & FLAG_PROGRESSBAR) != 0) { + ((SeekBarView) viewToInvalidate).setOuterColor(color); + } } if ((changeFlags & FLAG_TEXTCOLOR) != 0) { if ((changeFlags & FLAG_CHECKTAG) == 0 || checkTag(currentKey, viewToInvalidate)) { 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 5020f02e4..122a318db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -45,6 +45,8 @@ import org.telegram.ui.Cells.HintDialogCell; import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.TextCell; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.ForegroundColorSpanThemable; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.FilteredSearchView; @@ -56,8 +58,6 @@ import java.util.concurrent.ConcurrentHashMap; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.exoplayer2.util.Log; - public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -179,7 +179,6 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { @Override public void onDataSetChanged(int searchId) { waitingResponseCount--; - Log.d("kek", "data set change " + waitingResponseCount); lastGlobalSearchId = searchId; if (lastLocalSearchId != searchId) { searchResult.clear(); @@ -340,7 +339,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } } notifyDataSetChanged(); - if (delegate != null && req.offset_id == 0) { + if (delegate != null) { delegate.searchStateChanged(waitingResponseCount > 0, true); delegate.runResultsEnterAnimation(); } @@ -567,7 +566,6 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private void updateSearchResults(final ArrayList result, final ArrayList names, final ArrayList encUsers, final int searchId) { AndroidUtilities.runOnUIThread(() -> { waitingResponseCount--; - Log.d("kek", "update local search " + waitingResponseCount); if (searchId != lastSearchId) { return; } @@ -862,7 +860,10 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { view = new DialogCell(mContext, false, true); break; case 3: - view = new LoadingCell(mContext); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); + flickerLoadingView.setIsSingleCell(true); + view = flickerLoadingView; break; case 4: view = new HashtagSearchCell(mContext); @@ -872,7 +873,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { @Override public boolean onInterceptTouchEvent(MotionEvent e) { if (getParent() != null && getParent().getParent() != null) { - getParent().getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1)); + getParent().getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1) || canScrollHorizontally(1)); } return super.onInterceptTouchEvent(e); } @@ -981,7 +982,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } if (nameSearch != null && (index = AndroidUtilities.indexOfIgnoreCase(nameSearch, foundUserName)) != -1) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(nameSearch); - spannableStringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); name = spannableStringBuilder; } else if (un != null) { if (foundUserName.startsWith("@")) { @@ -998,7 +999,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } else { index++; } - spannableStringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } username = spannableStringBuilder; } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index 685e1444a..421be5915 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -258,6 +258,16 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { settingsIcon = R.drawable.menu_settings_14; inviteIcon = R.drawable.menu_secret_ny; helpIcon = R.drawable.menu_help; + } else if (eventType == 2) { + newGroupIcon = R.drawable.menu_groups_hw; + newSecretIcon = R.drawable.menu_secret_hw; + newChannelIcon = R.drawable.menu_broadcast_hw; + contactsIcon = R.drawable.menu_contacts_hw; + callsIcon = R.drawable.menu_calls_hw; + savedIcon = R.drawable.menu_bookmarks_hw; + settingsIcon = R.drawable.menu_settings_hw; + inviteIcon = R.drawable.menu_invite_hw; + helpIcon = R.drawable.menu_help_hw; } else { newGroupIcon = R.drawable.menu_groups; newSecretIcon = R.drawable.menu_secret; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java index 2553cfd2e..0b01b32d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java @@ -18,6 +18,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; @@ -84,6 +85,14 @@ public class FiltersView extends RecyclerListView { public boolean supportsPredictiveItemAnimations() { return false; } + + @Override + public void onInitializeAccessibilityNodeInfo(@NonNull Recycler recycler, @NonNull State state, @NonNull AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(recycler, state, info); + if (!isEnabled()) { + info.setVisibleToUser(false); + } + } }; layoutManager.setOrientation(HORIZONTAL); setLayoutManager(layoutManager); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index 3e560474a..eb132bce5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -99,6 +99,12 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca } } + public void updateLiveLocationCell() { + if (shareLiveLocationPotistion > 0) { + notifyItemChanged(shareLiveLocationPotistion); + } + } + public void updateLiveLocations() { if (!currentLiveLocations.isEmpty()) { notifyItemRangeChanged(2, currentLiveLocations.size(), new Object()); @@ -212,7 +218,9 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca @Override public int getItemCount() { - if (locationType == LocationActivity.LOCATION_TYPE_GROUP_VIEW) { + if (locationType == LocationActivity.LOCATION_TYPE_LIVE_VIEW) { + return 2; + } else if (locationType == LocationActivity.LOCATION_TYPE_GROUP_VIEW) { return 2; } else if (locationType == LocationActivity.LOCATION_TYPE_GROUP) { return 2; @@ -221,13 +229,13 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca } else if (locationType == 2) { return 2 + currentLiveLocations.size(); } else { - if (searching || !searching && places.isEmpty()) { + if (searching || places.isEmpty()) { return (locationType != 0 ? 6 : 5) + (needEmptyView ? 1 : 0); } if (locationType == 1) { - return 5 + places.size() + (places.isEmpty() ? 0 : 1) + (needEmptyView ? 1 : 0); + return 6 + places.size() + (needEmptyView ? 1 : 0); } else { - return 4 + places.size() + (places.isEmpty() ? 0 : 1) + (needEmptyView ? 1 : 0); + return 5 + places.size() + (needEmptyView ? 1 : 0); } } } @@ -336,7 +344,9 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca break; case 7: SharingLiveLocationCell locationCell = (SharingLiveLocationCell) holder.itemView; - if (chatLocation != null) { + if (locationType == LocationActivity.LOCATION_TYPE_LIVE_VIEW) { + locationCell.setDialog(currentMessageObject, gpsLocation); + } else if (chatLocation != null) { locationCell.setDialog(dialogId, chatLocation); } else if (currentMessageObject != null && position == 1) { locationCell.setDialog(currentMessageObject, gpsLocation); @@ -392,6 +402,9 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca if (position == 0) { return 0; } + if (locationType == LocationActivity.LOCATION_TYPE_LIVE_VIEW) { + return 7; + } if (needEmptyView && position == getItemCount() - 1) { return 10; } @@ -436,7 +449,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca return 9; } else if (position == 4) { return 2; - } else if (searching || !searching && places.isEmpty()) { + } else if (searching || places.isEmpty()) { return 4; } else if (position == places.size() + 5) { return 5; @@ -448,7 +461,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca return 9; } else if (position == 3) { return 2; - } else if (searching || !searching && places.isEmpty()) { + } else if (searching || places.isEmpty()) { return 4; } else if (position == places.size() + 4) { return 5; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index dbb4c4980..3975d05b1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -48,6 +48,7 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import androidx.recyclerview.widget.RecyclerView; @@ -65,8 +66,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { private long dialog_id; private TLRPC.ChatFull info; private SearchAdapterHelper searchAdapterHelper; - private ArrayList searchResultUsernames; - private SparseArray searchResultUsernamesMap; + private ArrayList searchResultUsernames; + private SparseArray searchResultUsernamesMap; private Runnable searchGlobalRunnable; private ArrayList searchResultHashtags; private ArrayList searchResultCommands; @@ -683,9 +684,9 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } final String usernameString = result.toString().toLowerCase(); boolean hasSpace = usernameString.indexOf(' ') >= 0; - ArrayList newResult = new ArrayList<>(); + ArrayList newResult = new ArrayList<>(); final SparseArray newResultsHashMap = new SparseArray<>(); - final SparseArray newMap = new SparseArray<>(); + final SparseArray newMap = new SparseArray<>(); ArrayList inlineBots = MediaDataController.getInstance(currentAccount).inlineBots; if (!usernameOnly && needBotContext && dogPostion == 0 && !inlineBots.isEmpty()) { int count = 0; @@ -706,61 +707,96 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } } final TLRPC.Chat chat; + int threadId; if (parentFragment != null) { chat = parentFragment.getCurrentChat(); + threadId = parentFragment.getThreadId(); } else if (info != null) { chat = messagesController.getChat(info.id); + threadId = 0; } else { chat = null; + threadId = 0; } if (chat != null && info != null && info.participants != null && (!ChatObject.isChannel(chat) || chat.megagroup)) { - for (int a = 0; a < info.participants.participants.size(); a++) { - TLRPC.ChatParticipant chatParticipant = info.participants.participants.get(a); - TLRPC.User user = messagesController.getUser(chatParticipant.user_id); - if (user == null || !usernameOnly && UserObject.isUserSelf(user) || newResultsHashMap.indexOfKey(user.id) >= 0) { - continue; - } - if (usernameString.length() == 0) { - if (!user.deleted) { - newResult.add(user); + for (int a = -1; a < info.participants.participants.size(); a++) { + String username; + String firstName; + String lastName; + TLObject object; + int id; + if (a == -1) { + if (chat == null) { + continue; } + if (usernameString.length() == 0) { + newResult.add(chat); + continue; + } + firstName = chat.title; + lastName = null; + username = chat.username; + object = chat; + id = -chat.id; } else { - if (user.username != null && user.username.length() > 0 && user.username.toLowerCase().startsWith(usernameString)) { - newResult.add(user); - newMap.put(user.id, user); - } else { - if (user.first_name != null && user.first_name.length() > 0 && user.first_name.toLowerCase().startsWith(usernameString)) { + TLRPC.ChatParticipant chatParticipant = info.participants.participants.get(a); + TLRPC.User user = messagesController.getUser(chatParticipant.user_id); + if (user == null || !usernameOnly && UserObject.isUserSelf(user) || newResultsHashMap.indexOfKey(user.id) >= 0) { + continue; + } + if (usernameString.length() == 0) { + if (!user.deleted) { newResult.add(user); - newMap.put(user.id, user); - } else if (user.last_name != null && user.last_name.length() > 0 && user.last_name.toLowerCase().startsWith(usernameString)) { - newResult.add(user); - newMap.put(user.id, user); - } else if (hasSpace && ContactsController.formatName(user.first_name, user.last_name).toLowerCase().startsWith(usernameString)) { - newResult.add(user); - newMap.put(user.id, user); + continue; } } + firstName = user.first_name; + lastName = user.last_name; + username = user.username; + object = user; + id = user.id; + } + if (!TextUtils.isEmpty(username) && username.toLowerCase().startsWith(usernameString) || + !TextUtils.isEmpty(firstName) && firstName.toLowerCase().startsWith(usernameString) || + !TextUtils.isEmpty(lastName) && lastName.toLowerCase().startsWith(usernameString) || + hasSpace && ContactsController.formatName(firstName, lastName).toLowerCase().startsWith(usernameString)) { + newResult.add(object); + newMap.put(id, object); } } } - Collections.sort(newResult, (lhs, rhs) -> { - if (newMap.indexOfKey(lhs.id) >= 0 && newMap.indexOfKey(rhs.id) >= 0) { + Collections.sort(newResult, new Comparator() { + + private int getId(TLObject object) { + if (object instanceof TLRPC.User) { + return ((TLRPC.User) object).id; + } else { + return -((TLRPC.Chat) object).id; + } + } + + @Override + public int compare(TLObject lhs, TLObject rhs) { + int id1 = getId(lhs); + int id2 = getId(rhs); + if (newMap.indexOfKey(id1) >= 0 && newMap.indexOfKey(id2) >= 0) { + return 0; + } else if (newMap.indexOfKey(id1) >= 0) { + return -1; + } else if (newMap.indexOfKey(id2) >= 0) { + return 1; + } + int lhsNum = users.indexOf(id1); + int rhsNum = users.indexOf(id2); + if (lhsNum != -1 && rhsNum != -1) { + return lhsNum < rhsNum ? -1 : (lhsNum == rhsNum ? 0 : 1); + } else if (lhsNum != -1 && rhsNum == -1) { + return -1; + } else if (lhsNum == -1 && rhsNum != -1) { + return 1; + } return 0; - } else if (newMap.indexOfKey(lhs.id) >= 0) { - return -1; - } else if (newMap.indexOfKey(rhs.id) >= 0) { - return 1; } - int lhsNum = users.indexOf(lhs.id); - int rhsNum = users.indexOf(rhs.id); - if (lhsNum != -1 && rhsNum != -1) { - return lhsNum < rhsNum ? -1 : (lhsNum == rhsNum ? 0 : 1); - } else if (lhsNum != -1 && rhsNum == -1) { - return -1; - } else if (lhsNum == -1 && rhsNum != -1) { - return 1; - } - return 0; }); searchResultHashtags = null; searchResultCommands = null; @@ -787,9 +823,14 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { req.channel = MessagesController.getInputChannel(chat); req.limit = 20; req.offset = 0; - TLRPC.TL_channelParticipantsSearch channelParticipantsSearch = new TLRPC.TL_channelParticipantsSearch(); - channelParticipantsSearch.q = usernameString; - req.filter = channelParticipantsSearch; + TLRPC.TL_channelParticipantsMentions channelParticipantsMentions = new TLRPC.TL_channelParticipantsMentions(); + channelParticipantsMentions.flags |= 1; + channelParticipantsMentions.q = usernameString; + if (threadId != 0) { + channelParticipantsMentions.flags |= 2; + channelParticipantsMentions.top_msg_id = threadId; + } + req.filter = channelParticipantsMentions; final int currentReqId = ++channelLastReqId; channelReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (channelReqId != 0 && currentReqId == channelLastReqId && searchResultUsernamesMap != null && searchResultUsernames != null) { @@ -887,7 +928,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } } - private void showUsersResult(ArrayList newResult, SparseArray newMap, boolean notify) { + private void showUsersResult(ArrayList newResult, SparseArray newMap, boolean notify) { searchResultUsernames = newResult; searchResultUsernamesMap = newMap; if (cancelDelayRunnable != null) { @@ -1080,7 +1121,12 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } } else { if (searchResultUsernames != null) { - ((MentionCell) holder.itemView).setUser(searchResultUsernames.get(position)); + TLObject object = searchResultUsernames.get(position); + if (object instanceof TLRPC.User) { + ((MentionCell) holder.itemView).setUser((TLRPC.User) object); + } else if (object instanceof TLRPC.Chat) { + ((MentionCell) holder.itemView).setChat((TLRPC.Chat) object); + } } else if (searchResultHashtags != null) { ((MentionCell) holder.itemView).setText(searchResultHashtags.get(position)); } else if (searchResultSuggestions != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 1a1603ade..2bd2de26e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -33,6 +33,7 @@ import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.UserCell; +import org.telegram.ui.Components.ForegroundColorSpanThemable; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; @@ -330,7 +331,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { } else { index++; } - spannableStringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } username = spannableStringBuilder; } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java index a66be29ea..89470453e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java @@ -463,14 +463,16 @@ public class SearchAdapterHelper { state.step(); } state.dispose(); - MessagesStorage.getInstance(currentAccount).getDatabase().commitTransaction(); - if (arrayList.size() >= 100) { - MessagesStorage.getInstance(currentAccount).getDatabase().beginTransaction(); + if (arrayList.size() > 100) { + state = MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("DELETE FROM hashtag_recent_v2 WHERE id = ?"); for (int a = 100; a < arrayList.size(); a++) { - MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("DELETE FROM hashtag_recent_v2 WHERE id = '" + arrayList.get(a).hashtag + "'").stepThis().dispose(); + state.requery(); + state.bindString(1, arrayList.get(a).hashtag); + state.step(); } - MessagesStorage.getInstance(currentAccount).getDatabase().commitTransaction(); + state.dispose(); } + MessagesStorage.getInstance(currentAccount).getDatabase().commitTransaction(); } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersSearchAdapter.java index 340555b1b..40cb3b839 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersSearchAdapter.java @@ -1,6 +1,7 @@ package org.telegram.ui.Adapters; import android.content.Context; +import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.text.TextUtils; @@ -339,11 +340,13 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter { View view = null; switch (viewType) { case 0: - view = new StickerEmojiCell(context) { + StickerEmojiCell stickerEmojiCell = new StickerEmojiCell(context) { public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(82), MeasureSpec.EXACTLY)); } }; + view = stickerEmojiCell; + stickerEmojiCell.getImageView().setLayerNum(3); break; case 1: view = new EmptyCell(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 52a416e1f..8b9c0ea7f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -859,7 +859,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } public boolean handleTouchEvent(MotionEvent event) { - if (!closeAnimationInProgress && fullscreenVideoContainer.getVisibility() != VISIBLE && !textSelectionHelper.isSelectionMode()) { + if (pageSwitchAnimation == null && !closeAnimationInProgress && fullscreenVideoContainer.getVisibility() != VISIBLE && !textSelectionHelper.isSelectionMode()) { if (event != null && event.getAction() == MotionEvent.ACTION_DOWN && !startedTracking && !maybeStartTracking) { startedTrackingPointerId = event.getPointerId(0); maybeStartTracking = true; @@ -3621,7 +3621,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; windowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW - 1; - windowLayoutParams.softInputMode = SharedConfig.smoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; if (Build.VERSION.SDK_INT >= 21) { windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | @@ -4010,10 +4010,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return false; } - if (messageObject != null) { - webpage = messageObject.messageOwner.media.webpage; - } - String anchor = null; if (messageObject != null) { webpage = messageObject.messageOwner.media.webpage; @@ -4084,7 +4080,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return; } - if (!pagesStack.isEmpty() && pagesStack.get(0) == webPageFinal && webPage.cached_page != null) { + if (!pagesStack.isEmpty() && pagesStack.get(0) == webPageFinal) { if (messageObject != null) { messageObject.messageOwner.media.webpage = webPage; TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); 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 401d58a1f..f54e44a98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java @@ -95,9 +95,7 @@ public class AboutLinkCell extends FrameLayout { } oldText = text; stringBuilder = new SpannableStringBuilder(oldText); - if (parseLinks) { - MessageObject.addLinks(false, stringBuilder, false, false); - } + MessageObject.addLinks(false, stringBuilder, false, false, !parseLinks); Emoji.replaceEmoji(stringBuilder, Theme.profile_aboutTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); if (TextUtils.isEmpty(value)) { valueTextView.setVisibility(GONE); 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 6e334e9b4..4f4dc2ee0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -8,10 +8,13 @@ package org.telegram.ui.Cells; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.Keyframe; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.ColorStateList; @@ -93,6 +96,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedFileDrawable; +import org.telegram.ui.Components.AnimatedNumberLayout; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioVisualizerDrawable; import org.telegram.ui.Components.AvatarDrawable; @@ -112,6 +116,7 @@ import org.telegram.ui.Components.RoundVideoPlayingDrawable; import org.telegram.ui.Components.SeekBar; import org.telegram.ui.Components.SeekBarAccessibilityDelegate; import org.telegram.ui.Components.SeekBarWaveform; +import org.telegram.ui.Components.SlotsDrawable; import org.telegram.ui.Components.StaticLayoutEx; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TimerParticles; @@ -263,22 +268,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int angle; private float progressAlpha; private long lastUpdateTime; - private TransitionParams transitionParams = new TransitionParams(); - - private class TransitionParams { - int transitionType; - int fromX; - int fromY; - int fromWidth; - int fromHeight; - - void saveState() { - fromX = x; - fromY = y; - fromWidth = width; - fromHeight = height; - } - } } public static class PollButton { @@ -344,9 +333,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private float lastTouchX; private float lastTouchY; - private boolean drawPhotoCheckBox; + private boolean drawMediaCheckBox; private boolean drawSelectionBackground; - private CheckBoxBase photoCheckBox; + private CheckBoxBase mediaCheckBox; private CheckBoxBase checkBox; private boolean checkBoxVisible; private boolean checkBoxAnimationInProgress; @@ -438,6 +427,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private String currentUrl; private WebFile currentWebFile; + private WebFile lastWebFile; private boolean addedForTest; private boolean hasEmbed; @@ -576,14 +566,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean isMegagroup; public boolean isThreadChat; public boolean hasDiscussion; + public boolean isPinned; + private boolean wasPinned; public int linkedChatId; - public boolean hasLinkedChat; public boolean isRepliesChat; + public boolean isPinnedChat; private boolean isPressed; private boolean forwardName; private boolean isHighlighted; private boolean isHighlightedAnimated; private int highlightProgress; + private float currentSelectedBackgroundAlpha; private long lastHighlightProgressTime; private boolean mediaBackground; private boolean isMedia; @@ -625,11 +618,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private AvatarDrawable[] commentAvatarDrawables; private boolean[] commentAvatarImagesVisible; private StaticLayout commentLayout; + private AnimatedNumberLayout commentNumberLayout; + private boolean drawCommentNumber; private int commentArrowX; private int commentUnreadX; private boolean commentDrawUnread; private int commentWidth; + private int commentX; private int totalCommentWidth; + private int commentNumberWidth; private boolean drawCommentButton; private Rect commentButtonRect = new Rect(); private boolean commentButtonPressed; @@ -672,7 +669,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private StaticLayout[] forwardedNameLayout = new StaticLayout[2]; private int forwardedNameWidth; private boolean drawForwardedName; - private int forwardNameX; + private float forwardNameX; private int forwardNameY; private float[] forwardNameOffsetX = new float[2]; @@ -735,6 +732,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } }; + private int animateToStatusDrawableParams; + private int animateFromStatusDrawableParams; + private float statusDrawableProgress; + private boolean statusDrawableAnimationInProgress; + private ValueAnimator statusDrawableAnimator; + + private int overideShouldDrawTimeOnMedia; + private Runnable invalidateRunnable = new Runnable() { @Override public void run() { @@ -761,6 +766,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate avatarImage.setRoundRadius(AndroidUtilities.dp(21)); avatarDrawable = new AvatarDrawable(); replyImageReceiver = new ImageReceiver(this); + replyImageReceiver.setRoundRadius(AndroidUtilities.dp(2)); locationImageReceiver = new ImageReceiver(this); locationImageReceiver.setRoundRadius(AndroidUtilities.dp(26.1f)); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); @@ -830,7 +836,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate for (int a = 0; a < pollCheckBox.length; a++) { pollCheckBox[a] = new CheckBoxBase(this, 20); pollCheckBox[a].setDrawUnchecked(false); - pollCheckBox[a].setDrawBackgroundAsArc(9); + pollCheckBox[a].setBackgroundType(9); } } @@ -945,7 +951,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate isMono = true; } boolean ignore = false; - if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } if (!ignore) { @@ -1048,7 +1054,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate link = buffer.getSpans(off, off, URLSpanMono.class); } boolean ignore = false; - if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } if (!ignore) { @@ -1109,7 +1115,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Spannable buffer = (Spannable) currentMessageObject.linkDescription; ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); boolean ignore = false; - if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } if (!ignore) { @@ -1190,7 +1196,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Spannable buffer = (Spannable) currentMessageObject.linkDescription; ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); boolean ignore = false; - if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } if (!ignore) { @@ -1573,6 +1579,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean checkOtherButtonMotionEvent(MotionEvent event) { + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) && currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { + return false; + } boolean allow = currentMessageObject.type == 16; if (!allow) { allow = !(documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && currentMessageObject.type != 12 && documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC && documentAttachType != DOCUMENT_ATTACH_TYPE_VIDEO && documentAttachType != DOCUMENT_ATTACH_TYPE_GIF && currentMessageObject.type != 8 || hasGamePreview || hasInvoicePreview); @@ -2009,16 +2018,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (currentChat != null) { int id; + TLRPC.Chat chat = currentChat; if (currentMessageObject.messageOwner.fwd_from != null) { if ((currentMessageObject.messageOwner.fwd_from.flags & 16) != 0) { id = currentMessageObject.messageOwner.fwd_from.saved_from_msg_id; } else { id = currentMessageObject.messageOwner.fwd_from.channel_post; + chat = currentForwardChannel; } } else { id = 0; } - delegate.didPressChannelAvatar(this, currentChat, id, lastTouchX, lastTouchY); + delegate.didPressChannelAvatar(this, chat != null ? chat : currentChat, id, lastTouchX, lastTouchY); } } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { @@ -2149,7 +2160,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return false; } - if (currentMessageObject.hasValidGroupId() && currentMessagesGroup != null) { + if (currentMessageObject.hasValidGroupId() && currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { ViewGroup parent = (ViewGroup) getParent(); for (int i = 0; i < parent.getChildCount(); i++) { View v = parent.getChildAt(i); @@ -2609,7 +2620,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return true; } - if (currentPhoto == null && newPhoto != null || currentPhoto != null && newPhoto == null || currentPhoto != null && newPhoto != null && (currentPhoto.local_id != newPhoto.local_id || currentPhoto.volume_id != newPhoto.volume_id)) { + if (currentPhoto == null && newPhoto != null || currentPhoto != null && newPhoto == null || currentPhoto != null && (currentPhoto.local_id != newPhoto.local_id || currentPhoto.volume_id != newPhoto.volume_id)) { return true; } @@ -2626,22 +2637,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return true; } - String newNameString = null; - if (drawName && isChat && !currentMessageObject.isOutOwner()) { - if (currentUser != null) { - newNameString = UserObject.getUserName(currentUser); - } else if (currentChat != null) { - newNameString = currentChat.title; - } - } - - if (currentNameString == null && newNameString != null || currentNameString != null && newNameString == null || currentNameString != null && newNameString != null && !currentNameString.equals(newNameString)) { + String newNameString = isNeedAuthorName() ? getAuthorName() : null; + if (currentNameString == null && newNameString != null || currentNameString != null && newNameString == null || currentNameString != null && !currentNameString.equals(newNameString)) { return true; } if (drawForwardedName && currentMessageObject.needDrawForwarded()) { newNameString = currentMessageObject.getForwardedName(); - return currentForwardNameString == null && newNameString != null || currentForwardNameString != null && newNameString == null || currentForwardNameString != null && newNameString != null && !currentForwardNameString.equals(newNameString); + return currentForwardNameString == null && newNameString != null || currentForwardNameString != null && newNameString == null || currentForwardNameString != null && !currentForwardNameString.equals(newNameString); } return false; } @@ -2658,7 +2661,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentUser != null && currentUser.id == 0) { return (int) avatarImage.getCenterX(); } - return forwardNameX + forwardNameCenterX; + return (int) (forwardNameX + forwardNameCenterX); } public TLRPC.User getCurrentUser() { @@ -2675,8 +2678,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (checkBox != null) { checkBox.onDetachedFromWindow(); } - if (photoCheckBox != null) { - photoCheckBox.onDetachedFromWindow(); + if (mediaCheckBox != null) { + mediaCheckBox.onDetachedFromWindow(); } if (pollCheckBox != null) { for (int a = 0; a < pollCheckBox.length; a++) { @@ -2714,13 +2717,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (MediaController.getInstance().isPlayingMessage(currentMessageObject)) { Theme.getCurrentAudiVisualizerDrawable().setParentView(null); } + + if (statusDrawableAnimator != null) { + statusDrawableAnimator.removeAllListeners(); + statusDrawableAnimator.cancel(); + } + statusDrawableAnimationInProgress = false; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + if (currentMessageObject != null) { + currentMessageObject.animateComments = false; + } if (messageObjectToSet != null) { + messageObjectToSet.animateComments = false; setMessageContent(messageObjectToSet, groupedMessagesToSet, bottomNearToSet, topNearToSet); messageObjectToSet = null; groupedMessagesToSet = null; @@ -2728,8 +2741,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (checkBox != null) { checkBox.onAttachedToWindow(); } - if (photoCheckBox != null) { - photoCheckBox.onAttachedToWindow(); + if (mediaCheckBox != null) { + mediaCheckBox.onAttachedToWindow(); } if (pollCheckBox != null) { for (int a = 0; a < pollCheckBox.length; a++) { @@ -2794,7 +2807,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean messageChanged = currentMessageObject != messageObject || messageObject.forceUpdate; boolean dataChanged = currentMessageObject != null && currentMessageObject.getId() == messageObject.getId() && lastSendState == MessageObject.MESSAGE_SEND_STATE_EDITING && messageObject.isSent() || currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet) - || lastPostAuthor != messageObject.messageOwner.post_author; + || lastPostAuthor != messageObject.messageOwner.post_author + || wasPinned != isPinned; boolean groupChanged = groupedMessages != currentMessagesGroup; boolean pollChanged = false; if (drawCommentButton || 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))) { @@ -2845,6 +2859,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate groupChanged = newPosition != currentPosition; } if (messageChanged || dataChanged || groupChanged || pollChanged || isPhotoDataChanged(messageObject) || pinnedBottom != bottomNear || pinnedTop != topNear) { + wasPinned = isPinned; pinnedBottom = bottomNear; pinnedTop = topNear; currentMessageObject = messageObject; @@ -2862,8 +2877,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentMessagesGroup = null; currentPosition = null; } - drawPinnedTop = pinnedTop && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0); - drawPinnedBottom = pinnedBottom && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0); + if (currentMessagesGroup == null || currentMessagesGroup.isDocuments) { + drawPinnedTop = pinnedTop; + drawPinnedBottom = pinnedBottom; + } else { + drawPinnedTop = pinnedTop && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0); + drawPinnedBottom = pinnedBottom && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0); + } + photoImage.setCrossfadeWithOldImage(false); photoImage.setCrossfadeDuration(ImageReceiver.DEFAULT_CROSSFADE_DURATION); lastSendState = messageObject.messageOwner.send_state; @@ -2884,8 +2905,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawVideoSize = false; canStreamVideo = false; animatingNoSound = 0; - drawSideButton = !isRepliesChat && checkNeedDrawShareButton(messageObject) ? 1 : 0; - if (drawSideButton == 1 && messageObject.messageOwner.fwd_from != null && !messageObject.isOutOwner() && messageObject.messageOwner.fwd_from.saved_from_peer != null && messageObject.getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) { + drawSideButton = !isRepliesChat && checkNeedDrawShareButton(messageObject) && (currentPosition == null || currentPosition.last) ? 1 : 0; + if (isPinnedChat || drawSideButton == 1 && messageObject.messageOwner.fwd_from != null && !messageObject.isOutOwner() && messageObject.messageOwner.fwd_from.saved_from_peer != null && messageObject.getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) { drawSideButton = 2; } replyNameLayout = null; @@ -2914,7 +2935,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate resetPressedLink(-1); messageObject.forceUpdate = false; drawPhotoImage = false; - drawPhotoCheckBox = false; + drawMediaCheckBox = false; hasLinkPreview = false; hasOldCaptionPreview = false; hasGamePreview = false; @@ -2967,8 +2988,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ImageLoader.getInstance().removeTestWebFile(currentUrl); } addedForTest = false; - currentUrl = null; - currentWebFile = null; photoNotSet = false; drawBackground = true; drawName = false; @@ -3034,7 +3053,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (isRepliesChat) { comment = LocaleController.getString("ViewInChat", R.string.ViewInChat); } else { - comment = commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.formatPluralString("CommentsCount", commentCount); + if (LocaleController.isRTL) { + comment = commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.formatPluralString("CommentsCount", commentCount); + } else { + comment = commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.getPluralString("CommentsNoNumber", commentCount); + } ArrayList recentRepliers = getRecentRepliers(); if (commentCount != 0 && recentRepliers != null && !recentRepliers.isEmpty()) { createCommentUI(); @@ -3075,6 +3098,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } commentWidth = totalCommentWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(comment)); commentLayout = new StaticLayout(comment, Theme.chat_replyNamePaint, commentWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (commentCount != 0 && !LocaleController.isRTL) { + drawCommentNumber = true; + if (commentNumberLayout == null) { + commentNumberLayout = new AnimatedNumberLayout(this, Theme.chat_replyNamePaint); + commentNumberLayout.setNumber(commentCount, false); + } else { + commentNumberLayout.setNumber(commentCount, messageObject.animateComments); + } + messageObject.animateComments = false; + commentNumberWidth = commentNumberLayout.getWidth(); + totalCommentWidth += commentNumberWidth + AndroidUtilities.dp(4); + } else { + drawCommentNumber = false; + if (commentNumberLayout != null) { + commentNumberLayout.setNumber(1, false); + } + } totalCommentWidth += AndroidUtilities.dp(70 + avatarsOffset); } else { if (!isRepliesChat && commentCount > 0) { @@ -3084,10 +3124,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { commentLayout = null; } + drawCommentNumber = false; drawSideButton = isRepliesChat ? 2 : 3; } } else { commentLayout = null; + drawCommentNumber = false; } if (messageObject.type == 0) { @@ -3107,7 +3149,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80); } - drawName = messageObject.messageOwner.peer_id.channel_id != 0 && (!messageObject.isOutOwner() || messageObject.isMegagroup()); + drawName = isPinnedChat || messageObject.messageOwner.peer_id.channel_id != 0 && (!messageObject.isOutOwner() || messageObject.isMegagroup()); } availableTimeWidth = maxWidth; @@ -3123,7 +3165,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate hasGamePreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame && messageObject.messageOwner.media.game instanceof TLRPC.TL_game; hasInvoicePreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice; - hasLinkPreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPage; + hasLinkPreview = !messageObject.isRestrictedMessage && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPage; drawInstantView = hasLinkPreview && messageObject.messageOwner.media.webpage.cached_page != null; hasEmbed = hasLinkPreview && !TextUtils.isEmpty(messageObject.messageOwner.media.webpage.embed_url) && !messageObject.isGif(); boolean slideshow = false; @@ -3552,7 +3594,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoParentObject = document; documentAttach = document; documentAttachType = DOCUMENT_ATTACH_TYPE_ROUND; - } else if (MessageObject.isGifDocument(document)) { + } else if (MessageObject.isGifDocument(document, messageObject.hasValidGroupId())) { if (!messageObject.isGame() && !SharedConfig.autoplayGifs) { messageObject.gifState = 1; } @@ -3893,7 +3935,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setRoundRadius(AndroidUtilities.roundMessageSize / 2); canChangeRadius = false; autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (MessageObject.isGifDocument(document)) { + } else if (MessageObject.isGifDocument(document, messageObject.hasValidGroupId())) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); } String filter = currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter; @@ -4146,7 +4188,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate namesOffset -= AndroidUtilities.dp(1); } } else if (messageObject.type == 14) { - drawName = messageObject.isFromGroup() && messageObject.isMegagroup(); + drawName = messageObject.isFromGroup() && messageObject.isMegagroup() && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0); if (AndroidUtilities.isTablet()) { backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(drawAvatar ? 102 : 50), AndroidUtilities.dp(270)); } else { @@ -4158,6 +4200,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate setMessageObjectInternal(messageObject); totalHeight = AndroidUtilities.dp(82) + namesOffset; + if (currentPosition != null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) { + if ((currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { + totalHeight -= AndroidUtilities.dp(6); + mediaOffsetY -= AndroidUtilities.dp(6); + } + if ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { + totalHeight -= AndroidUtilities.dp(6); + } + } if (drawPinnedTop) { namesOffset -= AndroidUtilities.dp(1); } @@ -4502,7 +4553,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (maxTextWidth > 0) { + if (maxTextWidth > 0 && currentPosition == null) { backgroundWidth = maxTextWidth; maxWidth = maxTextWidth - AndroidUtilities.dp(31); } @@ -4517,16 +4568,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (docTitleLayout != null && docTitleLayout.getLineCount() > 1) { photoHeight += (docTitleLayout.getLineCount() - 1) * AndroidUtilities.dp(16); } - } - - if (!drawPhotoImage && TextUtils.isEmpty(messageObject.caption) && infoLayout != null) { - int lineCount = infoLayout.getLineCount(); - measureTime(messageObject); - int timeLeft = backgroundWidth - AndroidUtilities.dp(40 + 18 + 56 + 8) - infoWidth; - if (timeLeft < timeWidth) { - photoHeight += AndroidUtilities.dp(12); - } else if (lineCount == 1) { - photoHeight += AndroidUtilities.dp(4); + if (TextUtils.isEmpty(messageObject.caption) && infoLayout != null) { + int lineCount = infoLayout.getLineCount(); + measureTime(messageObject); + int timeLeft = backgroundWidth - AndroidUtilities.dp(40 + 18 + 56 + 8) - infoWidth; + if (timeLeft < timeWidth) { + photoHeight += AndroidUtilities.dp(12); + } else if (lineCount == 1) { + photoHeight += AndroidUtilities.dp(4); + } } } } else if (messageObject.type == 4) { //geo @@ -4571,6 +4621,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate double y = Math.round(offset - rad * Math.log((1 + Math.sin(lat * Math.PI / 180.0)) / (1 - Math.sin(lat * Math.PI / 180.0))) / 2) - (AndroidUtilities.dp(10.3f) << (21 - 15)); lat = (Math.PI / 2.0 - 2 * Math.atan(Math.exp((y - offset) / rad))) * 180.0 / Math.PI; currentUrl = AndroidUtilities.formapMapUrl(currentAccount, lat, lon, (int) (photoWidth / AndroidUtilities.density), (int) (photoHeight / AndroidUtilities.density), false, 15, provider); + lastWebFile = currentWebFile; currentWebFile = WebFile.createWithGeoPoint(lat, lon, point.access_hash, (int) (photoWidth / AndroidUtilities.density), (int) (photoHeight / AndroidUtilities.density), 15, Math.min(2, (int) Math.ceil(AndroidUtilities.density))); if (!(locationExpired = isCurrentLocationTimeExpired(messageObject))) { @@ -4667,7 +4718,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setImage(null, null, null, null, messageObject, 0); } else if (currentMapProvider == 2) { if (currentWebFile != null) { - photoImage.setImage(ImageLocation.getForWebFile(currentWebFile), null, null, null, messageObject, 0); + ImageLocation lastLocation = lastWebFile == null ? null : ImageLocation.getForWebFile(lastWebFile); + photoImage.setImage(ImageLocation.getForWebFile(currentWebFile), null, lastLocation, null, null, messageObject, 0); } } else { if (currentMapProvider == 3 || currentMapProvider == 4) { @@ -5116,7 +5168,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - int minWidth = (int) (Theme.chat_infoPaint.measureText("100%") + AndroidUtilities.dp(48) + timeWidth); + int minWidth = (int) (Theme.chat_infoPaint.measureText("100%") + AndroidUtilities.dp(100/*48*/)/* + timeWidth*/); if (currentMessagesGroup == null && (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) && photoWidth < minWidth) { photoWidth = minWidth; backgroundWidth = photoWidth + AndroidUtilities.dp(8); @@ -5232,11 +5284,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } boolean autoDownload = false; TLRPC.Document document = messageObject.getDocument(); - if (MessageObject.isGifDocument(document) || messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { + if (MessageObject.isGifDocument(document, messageObject.hasValidGroupId()) || messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); } TLRPC.VideoSize videoSize = MessageObject.getDocumentVideoThumb(document); - if (((MessageObject.isGifDocument(document) && messageObject.videoEditedInfo == null) || (!messageObject.isSending() && !messageObject.isEditing())) && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) { + if (((MessageObject.isGifDocument(document, messageObject.hasValidGroupId()) && messageObject.videoEditedInfo == null) || (!messageObject.isSending() && !messageObject.isEditing())) && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) { if (localFile != 1 && !messageObject.needDrawBluredPreview() && (localFile != 0 || messageObject.canStreamVideo() && autoDownload)) { autoPlayingMedia = true; if (!messageIdChanged) { @@ -5292,7 +5344,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate namesOffset += AndroidUtilities.dp(7); } totalHeight = photoHeight + AndroidUtilities.dp(14) + namesOffset + additionHeight; - if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { + if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0 && !currentMessageObject.isDocument()) { totalHeight -= AndroidUtilities.dp(3); } if (currentMessageObject.isDice()) { @@ -5301,7 +5353,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int additionalTop = 0; - if (currentPosition != null) { + if (currentPosition != null && !currentMessageObject.isDocument()) { photoWidth += getAdditionalWidthForPosition(currentPosition); if ((currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { photoHeight += AndroidUtilities.dp(4); @@ -5324,11 +5376,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate y = AndroidUtilities.dp(5); totalHeight -= AndroidUtilities.dp(4); } + if (currentPosition != null && currentMessagesGroup.isDocuments && currentMessagesGroup.messages.size() > 1) { + if ((currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { + totalHeight -= AndroidUtilities.dp(drawPhotoImage ? 3 : 6); + mediaOffsetY -= AndroidUtilities.dp(drawPhotoImage ? 3 : 6); + y -= AndroidUtilities.dp(drawPhotoImage ? 3 : 6); + } + if ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { + totalHeight -= AndroidUtilities.dp(drawPhotoImage ? 3 : 6); + } + } photoImage.setImageCoords(0, y + namesOffset + additionalTop, photoWidth, photoHeight); invalidate(); } - if (currentPosition == null && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0) { + if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0) { if (!messageObject.isRestrictedMessage && captionLayout == null && messageObject.caption != null) { try { currentCaption = messageObject.caption; @@ -5352,14 +5414,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int width = backgroundWidth - AndroidUtilities.dp(31); if (captionLayout != null && captionLayout.getLineCount() > 0) { captionWidth = width; - int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX(); captionHeight = captionLayout.getHeight(); totalHeight += captionHeight + AndroidUtilities.dp(9); - float lastLineWidth = captionLayout.getLineWidth(captionLayout.getLineCount() - 1) + captionLayout.getLineLeft(captionLayout.getLineCount() - 1); - if (width - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) { - totalHeight += AndroidUtilities.dp(14); - captionHeight += AndroidUtilities.dp(14); - captionNewLine = 2; + if (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX(); + float lastLineWidth = captionLayout.getLineWidth(captionLayout.getLineCount() - 1) + captionLayout.getLineLeft(captionLayout.getLineCount() - 1); + if (width - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) { + totalHeight += AndroidUtilities.dp(14); + captionHeight += AndroidUtilities.dp(14); + captionNewLine = 2; + } } } } catch (Exception e) { @@ -5367,7 +5431,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } - if (captionLayout == null && widthBeforeNewTimeLine != -1 && availableTimeWidth - widthBeforeNewTimeLine < timeWidth) { + if ((currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) && captionLayout == null && widthBeforeNewTimeLine != -1 && availableTimeWidth - widthBeforeNewTimeLine < timeWidth) { totalHeight += AndroidUtilities.dp(14); } @@ -5428,7 +5492,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate botButtonsByPosition.clear(); botButtonsLayout = null; } - if (currentPosition == null && (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageObject.messageOwner.reactions != null && !messageObject.messageOwner.reactions.results.isEmpty())) { + if (!messageObject.isRestrictedMessage && currentPosition == null && (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageObject.messageOwner.reactions != null && !messageObject.messageOwner.reactions.results.isEmpty())) { int rows; if (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) { @@ -5606,7 +5670,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasLinkPreview || hasGamePreview || hasInvoicePreview) { tl = tr = bl = br = minRad; } - if (forwardedNameLayout[0] != null || replyNameLayout != null) { + if (forwardedNameLayout[0] != null || replyNameLayout != null || drawNameLayout) { tl = tr = minRad; } if (captionLayout != null || drawCommentButton) { @@ -5650,10 +5714,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (messageIdChanged) { + currentUrl = null; + currentWebFile = null; + lastWebFile = null; loadingProgressLayout = null; animatingLoadingProgressProgress = 0; lastLoadingSizeTotal = 0; selectedBackgroundProgress = 0f; + if (statusDrawableAnimator != null) { + statusDrawableAnimator.removeAllListeners(); + statusDrawableAnimator.cancel(); + } + transitionParams.lastStatusDrawableParams = -1; + statusDrawableAnimationInProgress = false; } updateWaveform(); updateButtonState(false, dataChanged && !messageObject.cancelEditing, true); @@ -5824,6 +5897,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + @Override + public void invalidate(int l, int t, int r, int b) { + if (currentMessageObject == null) { + return; + } + super.invalidate(l, t, r, b); + if (invalidatesParent) { + if (getParent() != null) { + View parent = (View) getParent(); + parent.invalidate((int) getX() + l, (int) getY() + t, (int) getX() + r, (int) getY() + b); + } + } + } + public boolean isHighlightedAnimated() { return isHighlightedAnimated; } @@ -5994,7 +6081,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate docTitleLayout = new StaticLayout(str, Theme.chat_infoPaint, docTitleWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } return 0; - } else if (MessageObject.isGifDocument(documentAttach)) { + } else if (MessageObject.isGifDocument(documentAttach, messageObject.hasValidGroupId())) { documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; if (!messageObject.needDrawBluredPreview()) { @@ -6008,13 +6095,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return 0; } else { - drawPhotoImage = documentAttach.mime_type != null && documentAttach.mime_type.toLowerCase().startsWith("image/") || MessageObject.isDocumentHasThumb(documentAttach); + drawPhotoImage = documentAttach.mime_type != null && (documentAttach.mime_type.toLowerCase().startsWith("image/") || documentAttach.mime_type.toLowerCase().startsWith("video/mp4")) || MessageObject.isDocumentHasThumb(documentAttach); if (!drawPhotoImage) { maxWidth += AndroidUtilities.dp(30); } documentAttachType = DOCUMENT_ATTACH_TYPE_DOCUMENT; String name = FileLoader.getDocumentFileName(documentAttach); - if (name == null || name.length() == 0) { + if (name.length() == 0) { name = LocaleController.getString("AttachDocument", R.string.AttachDocument); } docTitleLayout = StaticLayoutEx.createStaticLayout(name, Theme.chat_docNamePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.MIDDLE, maxWidth, 2, false); @@ -6724,12 +6811,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate needNewVisiblePart = false; } - int buttonX = this.buttonX; - int buttonY = this.buttonY; + float buttonX = this.buttonX; + float buttonY = this.buttonY; if (transitionParams.animateButton) { - buttonX = (int) (transitionParams.animateFromButtonX * (1f - transitionParams.animateChangeProgress) + this.buttonX * (transitionParams.animateChangeProgress)); - buttonY = (int) (transitionParams.animateFromButtonY * (1f - transitionParams.animateChangeProgress) + this.buttonY * (transitionParams.animateChangeProgress)); - radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(44), buttonY + AndroidUtilities.dp(44)); + buttonX = transitionParams.animateFromButtonX * (1f - transitionParams.animateChangeProgress) + this.buttonX * (transitionParams.animateChangeProgress); + buttonY = (transitionParams.animateFromButtonY * (1f - transitionParams.animateChangeProgress) + this.buttonY * (transitionParams.animateChangeProgress)); + radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + AndroidUtilities.dp(44), (int) buttonY + AndroidUtilities.dp(44)); } if (transitionParams.animateBackgroundBoundsInner && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { int backgroundWidth = this.backgroundWidth - transitionParams.deltaLeft + transitionParams.deltaRight; @@ -6767,6 +6854,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate videoRadialProgress.setProgressColor(Theme.getColor(Theme.key_chat_mediaProgress)); boolean imageDrawn = false; + radialProgress.setCircleCrossfadeColor(null, 0.0f, 1.0f); if (currentMessageObject.type == 0) { if (currentMessageObject.isOutOwner()) { textX = getCurrentBackgroundLeft() + AndroidUtilities.dp(11) + getExtraTextX(); @@ -6882,7 +6970,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int size = AndroidUtilities.dp(48); buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); + radialProgress.setProgressRect((int) buttonX, (int ) buttonY, (int) buttonX + size, (int) buttonY + size); } imageDrawn = photoImage.draw(canvas); } @@ -6958,7 +7046,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int size = AndroidUtilities.dp(48); buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); + radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); } } if (currentMessageObject.isRoundVideo() && MediaController.getInstance().isPlayingMessage(currentMessageObject) && MediaController.getInstance().isVideoDrawingReady() && canvas.isHardwareAccelerated()) { @@ -7092,23 +7180,25 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate setDrawableBounds(iconDrawable, rect.centerX() - iconDrawable.getIntrinsicWidth() / 2, rect.centerY() - iconDrawable.getIntrinsicHeight() / 2); iconDrawable.draw(canvas); } - drawPhotoCheckBox = photoCheckBox != null && (checkBoxVisible || photoCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && currentMessagesGroup != null; - if (drawPhotoCheckBox && (photoCheckBox.isChecked() || photoCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && (!textIsSelectionMode())) { - Theme.chat_replyLinePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected)); - rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); - int[] rad = photoImage.getRoundRadius(); - rectPath.reset(); - for (int a = 0; a < rad.length; a++) { - radii[a * 2] = radii[a * 2 + 1] = rad[a]; + drawMediaCheckBox = mediaCheckBox != null && (checkBoxVisible || mediaCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && currentMessagesGroup != null; + if (drawMediaCheckBox && (mediaCheckBox.isChecked() || mediaCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && (!textIsSelectionMode())) { + if (!currentMessagesGroup.isDocuments) { + Theme.chat_replyLinePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected)); + rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); + int[] rad = photoImage.getRoundRadius(); + rectPath.reset(); + for (int a = 0; a < rad.length; a++) { + radii[a * 2] = radii[a * 2 + 1] = rad[a]; + } + rectPath.addRoundRect(rect, radii, Path.Direction.CW); + rectPath.close(); + canvas.drawPath(rectPath, Theme.chat_replyLinePaint); } - rectPath.addRoundRect(rect, radii, Path.Direction.CW); - rectPath.close(); - canvas.drawPath(rectPath, Theme.chat_replyLinePaint); - photoImage.setSideClip(AndroidUtilities.dp(14) * photoCheckBox.getProgress()); + photoImage.setSideClip(AndroidUtilities.dp(14) * mediaCheckBox.getProgress()); if (checkBoxAnimationInProgress) { - photoCheckBox.setBackgroundAlpha(checkBoxAnimationProgress); + mediaCheckBox.setBackgroundAlpha(checkBoxAnimationProgress); } else { - photoCheckBox.setBackgroundAlpha(checkBoxVisible ? 1.0f : photoCheckBox.getProgress()); + mediaCheckBox.setBackgroundAlpha(checkBoxVisible ? 1.0f : mediaCheckBox.getProgress()); } } else { photoImage.setSideClip(0); @@ -7143,8 +7233,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } + } else { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { + drawMediaCheckBox = mediaCheckBox != null && (checkBoxVisible || mediaCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && currentMessagesGroup != null; + if (drawMediaCheckBox) { + radialProgress.setCircleCrossfadeColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outTimeText : Theme.key_chat_inTimeText, checkBoxAnimationProgress, 1.0f - mediaCheckBox.getProgress()); + } + if (drawMediaCheckBox && !textIsSelectionMode() && (mediaCheckBox.isChecked() || mediaCheckBox.getProgress() != 0 || checkBoxAnimationInProgress)) { + if (checkBoxAnimationInProgress) { + mediaCheckBox.setBackgroundAlpha(checkBoxAnimationProgress); + if (radialProgress.getMiniIcon() == MediaActionDrawable.ICON_NONE) { + radialProgress.setMiniIconScale(checkBoxAnimationProgress); + } + } else { + mediaCheckBox.setBackgroundAlpha(checkBoxVisible ? 1.0f : mediaCheckBox.getProgress()); + } + } else if (mediaCheckBox != null) { + mediaCheckBox.setBackgroundAlpha(1.0f); + } + } } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (photoImage.getVisible() && !hasGamePreview && !currentMessageObject.needDrawBluredPreview()) { int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); @@ -7236,14 +7344,22 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate durationLayout.draw(canvas); canvas.restore(); - Drawable menuDrawable; - if (currentMessageObject.isOutOwner()) { - menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; - } else { - menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; + if (shouldDrawMenuDrawable()) { + Drawable menuDrawable; + if (currentMessageObject.isOutOwner()) { + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; + } else { + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; + } + setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == 0 ? 58 : 48), otherY = (int) buttonY - AndroidUtilities.dp(2)); + if (transitionParams.animateChangeProgress != 1f && transitionParams.animateShouldDrawMenuDrawable) { + menuDrawable.setAlpha((int) (255 * transitionParams.animateChangeProgress)); + } + menuDrawable.draw(canvas); + if (transitionParams.animateChangeProgress != 1f && transitionParams.animateShouldDrawMenuDrawable) { + menuDrawable.setAlpha(255); + } } - setDrawableBounds(menuDrawable, otherX = buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == 0 ? 58 : 48), otherY = buttonY - AndroidUtilities.dp(2)); - menuDrawable.draw(canvas); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { if (currentMessageObject.isOutOwner()) { Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); @@ -7297,7 +7413,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (captionLayout != null) { updateCaptionLayout(); } - if (currentPosition == null && !transitionParams.transformGroupToSingleMessage) { + if ((currentPosition == null || currentMessagesGroup != null && currentMessagesGroup.isDocuments) && !transitionParams.transformGroupToSingleMessage) { drawCaptionLayout(canvas, false, 1f); } @@ -7362,7 +7478,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } - int x; + float x; int titleY; int subtitleY; if (drawPhotoImage) { @@ -7410,10 +7526,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } else { - setDrawableBounds(menuDrawable, otherX = buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == 0 ? 58 : 48), otherY = buttonY - AndroidUtilities.dp(2)); + setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == 0 ? 58 : 48), otherY = (int) buttonY - AndroidUtilities.dp(2)); x = buttonX + AndroidUtilities.dp(53); - titleY = buttonY + AndroidUtilities.dp(4); - subtitleY = buttonY + AndroidUtilities.dp(27); + titleY = (int) buttonY + AndroidUtilities.dp(4); + subtitleY = (int) buttonY + AndroidUtilities.dp(27); if (docTitleLayout != null && docTitleLayout.getLineCount() > 1) { subtitleY += (docTitleLayout.getLineCount() - 1) * AndroidUtilities.dp(16) + AndroidUtilities.dp(2); } @@ -7425,7 +7541,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || videoButtonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); } } - menuDrawable.draw(canvas); + if (shouldDrawMenuDrawable()) { + if (transitionParams.animateChangeProgress != 1f && transitionParams.animateShouldDrawMenuDrawable) { + menuDrawable.setAlpha((int) (255 * transitionParams.animateChangeProgress)); + } + menuDrawable.draw(canvas); + if (transitionParams.animateChangeProgress != 1f && transitionParams.animateShouldDrawMenuDrawable) { + menuDrawable.setAlpha(255); + } + } try { if (docTitleLayout != null) { @@ -7465,6 +7589,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate transitionParams.recordDrawingState(); } + private boolean shouldDrawMenuDrawable() { + return currentMessagesGroup == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0; + } + private void drawBotButtons(Canvas canvas, ArrayList botButtons, float alpha) { int addX; if (currentMessageObject.isOutOwner()) { @@ -7509,7 +7637,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (button.button instanceof TLRPC.TL_keyboardButtonCallback || button.button instanceof TLRPC.TL_keyboardButtonRequestGeoLocation || button.button instanceof TLRPC.TL_keyboardButtonGame || button.button instanceof TLRPC.TL_keyboardButtonBuy || button.button instanceof TLRPC.TL_keyboardButtonUrlAuth) { boolean drawProgress = (button.button instanceof TLRPC.TL_keyboardButtonCallback || button.button instanceof TLRPC.TL_keyboardButtonGame || button.button instanceof TLRPC.TL_keyboardButtonBuy || button.button instanceof TLRPC.TL_keyboardButtonUrlAuth) && SendMessagesHelper.getInstance(currentAccount).isSendingCallback(currentMessageObject, button.button) || button.button instanceof TLRPC.TL_keyboardButtonRequestGeoLocation && SendMessagesHelper.getInstance(currentAccount).isSendingCurrentLocation(currentMessageObject, button.button); - if (drawProgress || !drawProgress && button.progressAlpha != 0) { + if (drawProgress || button.progressAlpha != 0) { Theme.chat_botProgressPaint.setAlpha(Math.min(255, (int) (button.progressAlpha * 255))); int x = button.x + button.width - AndroidUtilities.dp(9 + 3) + addX; rect.set(x, y + AndroidUtilities.dp(4), x + AndroidUtilities.dp(8), y + AndroidUtilities.dp(8 + 4)); @@ -7641,7 +7769,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate captionY -= AndroidUtilities.dp(shouldDrawTimeOnMedia() ? 41.3f : 43); } } else { - captionX = backgroundDrawableLeft + AndroidUtilities.dp(currentMessageObject.isOutOwner() || mediaBackground || !mediaBackground && drawPinnedBottom ? 11 : 17) + captionOffsetX; + captionX = backgroundDrawableLeft + AndroidUtilities.dp(currentMessageObject.isOutOwner() || mediaBackground || drawPinnedBottom ? 11 : 17) + captionOffsetX; captionY = totalHeight - captionHeight - AndroidUtilities.dp(drawPinnedTop ? 9 : 10); if (drawCommentButton && drawSideButton != 3) { captionY -= AndroidUtilities.dp(shouldDrawTimeOnMedia() ? 41.3f : 43); @@ -7707,7 +7835,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return MediaActionDrawable.ICON_CANCEL; } else if (buttonState == 2) { return MediaActionDrawable.ICON_PLAY; - } else if (buttonState == 3) { + } else { return autoPlayingMedia ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY; } } else if (buttonState == -1) { @@ -7750,7 +7878,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return maxWidth - backgroundWidth - AndroidUtilities.dp(57); } - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { int dWidth; if (AndroidUtilities.isTablet()) { dWidth = AndroidUtilities.getMinTabletSide(); @@ -7838,11 +7966,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate DownloadController.getInstance(currentAccount).addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, currentMessageObject, this); wasSending = true; buttonState = 4; - radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); + boolean sending = SendMessagesHelper.getInstance(currentAccount).isSendingMessage(currentMessageObject.getId()); + if (currentPosition != null && sending && buttonState == 4) { + drawRadialCheckBackground = true; + getIconForCurrentState(); + radialProgress.setIcon(MediaActionDrawable.ICON_CHECK, ifSame, animated); + } else { + radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); + } + radialProgress.setMiniIcon(MediaActionDrawable.ICON_NONE, ifSame, animated); if (!fromBot) { long[] progress = ImageLoader.getInstance().getFileProgressSizes(currentMessageObject.messageOwner.attachPath); float loadingProgress = 0; - if (progress == null && SendMessagesHelper.getInstance(currentAccount).isSendingMessage(currentMessageObject.getId())) { + if (progress == null && sending) { loadingProgress = 1.0f; } else if (progress != null) { loadingProgress = DownloadController.getProgress(progress); @@ -7856,12 +7992,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate getIconForCurrentState(); radialProgress.setIcon(MediaActionDrawable.ICON_CANCEL_NOPROFRESS, ifSame, false); radialProgress.setProgress(0, false); + radialProgress.setMiniIcon(MediaActionDrawable.ICON_NONE, ifSame, false); } } else { if (hasMiniProgress != 0) { radialProgress.setMiniProgressBackgroundColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outLoader : Theme.key_chat_inLoader)); boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); - if (!playing || playing && MediaController.getInstance().isMessagePaused()) { + if (!playing || MediaController.getInstance().isMessagePaused()) { buttonState = 0; } else { buttonState = 1; @@ -7891,7 +8028,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (fileExists) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); - if (!playing || playing && MediaController.getInstance().isMessagePaused()) { + if (!playing || MediaController.getInstance().isMessagePaused()) { buttonState = 0; } else { buttonState = 1; @@ -7930,7 +8067,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); float setProgress = 0; if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - if (!currentMessageObject.loadingCancelled && (documentAttachType == 0 && autoDownload || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isGifDocument(documentAttach) && autoDownload)) { + if (!currentMessageObject.loadingCancelled && (documentAttachType == 0 && autoDownload || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isGifDocument(documentAttach, currentMessageObject.hasValidGroupId()) && autoDownload)) { buttonState = 1; } else { buttonState = 0; @@ -8138,7 +8275,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int mask = MessageObject.POSITION_FLAG_LEFT | MessageObject.POSITION_FLAG_RIGHT; fullWidth = (currentPosition.flags & mask) == mask; } - if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || MessageObject.isGifDocument(documentAttach) && autoDownload) && canStreamVideo && hasDocLayout && fullWidth) { + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || MessageObject.isGifDocument(documentAttach, currentMessageObject.hasValidGroupId()) && autoDownload) && canStreamVideo && hasDocLayout && fullWidth) { drawVideoImageButton = true; getIconForCurrentState(); radialProgress.setIcon(autoPlayingMedia || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY, ifSame, animated); @@ -8333,7 +8470,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonState = -1; radialProgress.setIcon(getIconForCurrentState(), false, animated); } - } else if (buttonState == 3 || buttonState == 0 && drawVideoImageButton) { + } else if (buttonState == 3 || buttonState == 0) { if (hasMiniProgress == 2 && miniButtonState != 1) { miniButtonState = 1; radialProgress.setProgress(0, false); @@ -8343,7 +8480,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (buttonState == 4) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.isOut() && (currentMessageObject.isSending() || currentMessageObject.isEditing()) || currentMessageObject.isSendError()) { - if (delegate != null) { + if (delegate != null && radialProgress.getIcon() != MediaActionDrawable.ICON_CHECK) { delegate.didPressCancelSendButton(this); } } else { @@ -8445,35 +8582,48 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate String emoji = currentMessageObject.getDiceEmoji(); TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(emoji); if (stickerSet != null) { - if (!lottieDrawable.hasBaseDice() && stickerSet.documents.size() > 0) { - TLRPC.Document document = stickerSet.documents.get(0); - File path = FileLoader.getPathToAttach(document, true); - if (lottieDrawable.setBaseDice(path)) { - DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); - } else { - String fileName = FileLoader.getAttachFileName(document); - DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); - FileLoader.getInstance(currentAccount).loadFile(document, stickerSet, 1, 1); - } - } int value = currentMessageObject.getDiceValue(); - if (value >= 0 && value < stickerSet.documents.size()) { - if (!instant && currentMessageObject.isOut()) { - MessagesController.DiceFrameSuccess frameSuccess = MessagesController.getInstance(currentAccount).diceSuccess.get(emoji); - if (frameSuccess != null && frameSuccess.num == value) { - lottieDrawable.setOnFinishCallback(diceFinishCallback, frameSuccess.frame); + if ("\uD83C\uDFB0".equals(currentMessageObject.getDiceEmoji())) { + if (value >= 0 && value <= 64) { + ((SlotsDrawable) lottieDrawable).setDiceNumber(this, value, stickerSet, instant); + if (currentMessageObject.isOut()) { + lottieDrawable.setOnFinishCallback(diceFinishCallback, Integer.MAX_VALUE); + } + currentMessageObject.wasUnread = false; + } + if (!lottieDrawable.hasBaseDice() && stickerSet.documents.size() > 0) { + ((SlotsDrawable) lottieDrawable).setBaseDice(this, stickerSet); + } + } else { + if (!lottieDrawable.hasBaseDice() && stickerSet.documents.size() > 0) { + TLRPC.Document document = stickerSet.documents.get(0); + File path = FileLoader.getPathToAttach(document, true); + if (lottieDrawable.setBaseDice(path)) { + DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); + } else { + String fileName = FileLoader.getAttachFileName(document); + DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); + FileLoader.getInstance(currentAccount).loadFile(document, stickerSet, 1, 1); } } - TLRPC.Document document = stickerSet.documents.get(Math.max(value, 0)); - File path = FileLoader.getPathToAttach(document, true); - if (lottieDrawable.setDiceNumber(path, instant)) { - DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); - } else { - String fileName = FileLoader.getAttachFileName(document); - DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); - FileLoader.getInstance(currentAccount).loadFile(document, stickerSet, 1, 1); + if (value >= 0 && value < stickerSet.documents.size()) { + if (!instant && currentMessageObject.isOut()) { + MessagesController.DiceFrameSuccess frameSuccess = MessagesController.getInstance(currentAccount).diceSuccess.get(emoji); + if (frameSuccess != null && frameSuccess.num == value) { + lottieDrawable.setOnFinishCallback(diceFinishCallback, frameSuccess.frame); + } + } + TLRPC.Document document = stickerSet.documents.get(Math.max(value, 0)); + File path = FileLoader.getPathToAttach(document, true); + if (lottieDrawable.setDiceNumber(path, instant)) { + DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); + } else { + String fileName = FileLoader.getAttachFileName(document); + DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); + FileLoader.getInstance(currentAccount).loadFile(document, stickerSet, 1, 1); + } + currentMessageObject.wasUnread = false; } - currentMessageObject.wasUnread = false; } } else { MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(emoji, true, true); @@ -8531,7 +8681,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.setProgress(progress, true); if (uploadedSize == totalSize && currentPosition != null) { boolean sending = SendMessagesHelper.getInstance(currentAccount).isSendingMessage(currentMessageObject.getId()); - if (sending && buttonState == 1) { + if (sending && (buttonState == 1 || buttonState == 4 && documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC)) { drawRadialCheckBackground = true; getIconForCurrentState(); radialProgress.setIcon(MediaActionDrawable.ICON_CHECK, false, true); @@ -8662,12 +8812,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isFromUser()) { author = MessagesController.getInstance(currentAccount).getUser(fromId); } + boolean hasReplies = messageObject.hasReplies(); if (messageObject.scheduled || messageObject.isLiveLocation() || messageObject.messageOwner.edit_hide || messageObject.getDialogId() == 777000 || messageObject.messageOwner.via_bot_id != 0 || messageObject.messageOwner.via_bot_name != null || author != null && author.bot) { edited = false; - } else if (currentPosition == null || currentMessagesGroup == null) { + } else if (currentPosition == null || currentMessagesGroup == null || currentMessagesGroup.messages.isEmpty()) { edited = (messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || messageObject.isEditing(); } else { edited = false; + hasReplies = currentMessagesGroup.messages.get(0).hasReplies(); for (int a = 0, size = currentMessagesGroup.messages.size(); a < size; a++) { MessageObject object = currentMessagesGroup.messages.get(a); if ((object.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || object.isEditing()) { @@ -8697,13 +8849,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate viewsTextWidth = (int) Math.ceil(Theme.chat_timePaint.measureText(currentViewsString)); timeWidth += viewsTextWidth + Theme.chat_msgInViewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } - if (hasLinkedChat && isChat && isMegagroup && !isThreadChat && messageObject.hasReplies()) { + if (isChat && isMegagroup && !isThreadChat && hasReplies) { currentRepliesString = String.format("%s", LocaleController.formatShortNumber(getRepliesCount(), null)); repliesTextWidth = (int) Math.ceil(Theme.chat_timePaint.measureText(currentRepliesString)); timeWidth += repliesTextWidth + Theme.chat_msgInRepliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } else { currentRepliesString = null; } + if (isPinned) { + timeWidth += Theme.chat_msgInPinnedDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3); + } if (messageObject.scheduled) { if (messageObject.isSendError()) { timeWidth += AndroidUtilities.dp(18); @@ -8748,9 +8903,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean checkNeedDrawShareButton(MessageObject messageObject) { - if ((currentPosition != null && !currentPosition.last) || currentMessageObject.deleted) { + if (currentMessageObject.deleted) { return false; } + if (currentPosition != null) { + if (!currentMessagesGroup.isDocuments && !currentPosition.last) { + return false; + } + } return messageObject.needDrawShareButton(); } @@ -8858,9 +9018,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate viaWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(viaString, 0, viaString.length())); } - boolean authorName = (!pinnedTop || ChatObject.isChannel(currentChat) && !currentChat.megagroup) && drawName && isChat && (!currentMessageObject.isOutOwner() || currentMessageObject.isMegagroup() && currentMessageObject.isFromGroup()); + boolean needAuthorName = isNeedAuthorName(); boolean viaBot = (messageObject.messageOwner.fwd_from == null || messageObject.type == 14) && viaUsername != null; - if (!hasPsaHint && (authorName || viaBot)) { + if (!hasPsaHint && (needAuthorName || viaBot)) { drawNameLayout = true; nameWidth = getMaxNameWidth(); if (nameWidth < 0) { @@ -8889,14 +9049,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate adminWidth = 0; } - if (authorName) { - if (currentUser != null) { - currentNameString = UserObject.getUserName(currentUser); - } else if (currentChat != null) { - currentNameString = currentChat.title; - } else { - currentNameString = "DELETED"; - } + if (needAuthorName) { + currentNameString = getAuthorName(); } else { currentNameString = ""; } @@ -8928,7 +9082,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } try { nameLayout = new StaticLayout(nameStringFinal, Theme.chat_namePaint, nameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - if (nameLayout != null && nameLayout.getLineCount() > 0) { + if (nameLayout.getLineCount() > 0) { nameWidth = (int) Math.ceil(nameLayout.getLineWidth(0)); if (!messageObject.isAnyKindOfSticker()) { namesOffset += AndroidUtilities.dp(19); @@ -8984,7 +9138,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); - } else if (currentForwardName != null) { + } else { currentForwardNameString = currentForwardName; } @@ -9087,7 +9241,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.replyMessageObject.isRoundVideo()) { replyImageReceiver.setRoundRadius(AndroidUtilities.dp(22)); } else { - replyImageReceiver.setRoundRadius(0); + replyImageReceiver.setRoundRadius(AndroidUtilities.dp(2)); } currentReplyPhoto = photoSize; replyImageReceiver.setImage(ImageLocation.getForObject(photoSize, photoObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoObject), "50_50_b", size, null, messageObject.replyMessageObject, cacheType); @@ -9167,7 +9321,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); - } else if (currentForwardName != null) { + } else { currentForwardNameString = currentForwardName; } name = getForwardedMessageText(messageObject); @@ -9239,6 +9393,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate requestLayout(); } + private boolean isNeedAuthorName() { + return isPinnedChat && currentMessageObject.type == 0 || (!pinnedTop || ChatObject.isChannel(currentChat) && !currentChat.megagroup) && drawName && isChat && (!currentMessageObject.isOutOwner() || currentMessageObject.isMegagroup() && currentMessageObject.isFromGroup()); + } + + private String getAuthorName() { + if (currentUser != null) { + return UserObject.getUserName(currentUser); + } else if (currentChat != null) { + return currentChat.title; + } else { + return "DELETED"; + } + } + private String getForwardedMessageText(MessageObject messageObject) { if (hasPsaHint) { String forwardedString = LocaleController.getString("PsaMessage_" + messageObject.messageOwner.fwd_from.psa_type); @@ -9320,7 +9488,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate forceLayout(); return; } - if (!wasLayout && animationRunning) { + if (!wasLayout) { onLayout(false, getLeft(), getTop(), getRight(), getBottom()); } @@ -9348,7 +9516,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate seekBar.setColors(Theme.getColor(Theme.key_chat_inAudioSeekbar), Theme.getColor(Theme.key_chat_inAudioCacheSeekbar), Theme.getColor(Theme.key_chat_inAudioSeekbarFill), Theme.getColor(Theme.key_chat_inAudioSeekbarFill), Theme.getColor(Theme.key_chat_inAudioSeekbarSelected)); } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { - documentAttachType = DOCUMENT_ATTACH_TYPE_MUSIC; if (currentMessageObject.isOutOwner()) { seekBar.setColors(Theme.getColor(Theme.key_chat_outAudioSeekbar), Theme.getColor(Theme.key_chat_outAudioCacheSeekbar), Theme.getColor(Theme.key_chat_outAudioSeekbarFill), Theme.getColor(Theme.key_chat_outAudioSeekbarFill), Theme.getColor(Theme.key_chat_outAudioSeekbarSelected)); } else { @@ -9377,12 +9544,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Drawable currentBackgroundShadowDrawable; int additionalTop = 0; int additionalBottom = 0; + boolean forceMediaByGroup = currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0 && currentMessagesGroup.isDocuments && !drawPinnedBottom; if (currentMessageObject.isOutOwner()) { - if (transitionParams.changePinnedBottomProgress != 1) { - currentBackgroundDrawable = Theme.chat_msgOutMediaDrawable; - currentBackgroundSelectedDrawable = Theme.chat_msgOutMediaSelectedDrawable; - transitionParams.drawPinnedBottomBackground = true; - } else if (!mediaBackground && !drawPinnedBottom) { + if (transitionParams.changePinnedBottomProgress >= 1 && !mediaBackground && !drawPinnedBottom && !forceMediaByGroup) { currentBackgroundDrawable = Theme.chat_msgOutDrawable; currentBackgroundSelectedDrawable = Theme.chat_msgOutSelectedDrawable; transitionParams.drawPinnedBottomBackground = false; @@ -9399,14 +9563,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } backgroundDrawableLeft = layoutWidth - backgroundWidth - (!mediaBackground ? 0 : AndroidUtilities.dp(9)); backgroundDrawableRight = backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(3)); - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (!currentPosition.edge) { backgroundDrawableRight += AndroidUtilities.dp(10); } } int backgroundLeft = backgroundDrawableLeft; - if (transitionParams.changePinnedBottomProgress != 1) { - backgroundDrawableRight -= AndroidUtilities.dp(6); + if (!forceMediaByGroup && transitionParams.changePinnedBottomProgress != 1) { + if (!mediaBackground) { + backgroundDrawableRight -= AndroidUtilities.dp(6); + } } else if (!mediaBackground && drawPinnedBottom) { backgroundDrawableRight -= AndroidUtilities.dp(6); } @@ -9435,18 +9601,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { offsetBottom = AndroidUtilities.dp(2); } - backgroundDrawableTop = additionalTop + (drawPinnedTop || drawPinnedTop && drawPinnedBottom ? 0 : AndroidUtilities.dp(1)); + backgroundDrawableTop = additionalTop + (drawPinnedTop ? 0 : AndroidUtilities.dp(1)); int backgroundHeight = layoutHeight - offsetBottom + additionalBottom; backgroundDrawableBottom = backgroundDrawableTop + backgroundHeight; - setDrawableBoundsInner(currentBackgroundDrawable, backgroundLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); - setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); + if (forceMediaByGroup) { + setDrawableBoundsInner(currentBackgroundDrawable, backgroundLeft, backgroundDrawableTop - additionalTop, backgroundDrawableRight, backgroundHeight - additionalBottom + 10); + setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundDrawableLeft, backgroundDrawableTop, backgroundDrawableRight - AndroidUtilities.dp(6), backgroundHeight); + } else { + setDrawableBoundsInner(currentBackgroundDrawable, backgroundLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); + setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); + } setDrawableBoundsInner(currentBackgroundShadowDrawable, backgroundLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); } else { - if (transitionParams.changePinnedBottomProgress != 1) { - currentBackgroundDrawable = Theme.chat_msgInMediaDrawable; - currentBackgroundSelectedDrawable = Theme.chat_msgInMediaSelectedDrawable; - transitionParams.drawPinnedBottomBackground = true; - } else if (!mediaBackground && !drawPinnedBottom) { + if (transitionParams.changePinnedBottomProgress >= 1 && !mediaBackground && !drawPinnedBottom && !forceMediaByGroup) { currentBackgroundDrawable = Theme.chat_msgInDrawable; currentBackgroundSelectedDrawable = Theme.chat_msgInSelectedDrawable; transitionParams.drawPinnedBottomBackground = false; @@ -9464,7 +9631,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate backgroundDrawableLeft = AndroidUtilities.dp((isChat && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); backgroundDrawableRight = backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(3)); - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (!currentPosition.edge) { backgroundDrawableLeft -= AndroidUtilities.dp(10); backgroundDrawableRight += AndroidUtilities.dp(10); @@ -9473,9 +9640,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate backgroundDrawableLeft += (int) Math.ceil(currentPosition.leftSpanOffset / 1000.0f * getGroupPhotosWidth()); } } - if ((!mediaBackground && drawPinnedBottom) || transitionParams.changePinnedBottomProgress != 1) { - backgroundDrawableRight -= AndroidUtilities.dp(6); - backgroundDrawableLeft += AndroidUtilities.dp(6); + if ((!mediaBackground && drawPinnedBottom) || !forceMediaByGroup && transitionParams.changePinnedBottomProgress != 1) { + if (!(!drawPinnedBottom && mediaBackground)) { + backgroundDrawableRight -= AndroidUtilities.dp(6); + } + if (!mediaBackground) { + backgroundDrawableLeft += AndroidUtilities.dp(6); + } + } if (currentPosition != null) { if ((currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) == 0) { @@ -9501,15 +9673,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { offsetBottom = AndroidUtilities.dp(2); } - backgroundDrawableTop = additionalTop + (drawPinnedTop || drawPinnedTop && drawPinnedBottom ? 0 : AndroidUtilities.dp(1)); + backgroundDrawableTop = additionalTop + (drawPinnedTop ? 0 : AndroidUtilities.dp(1)); int backgroundHeight = layoutHeight - offsetBottom + additionalBottom; backgroundDrawableBottom = backgroundDrawableTop + backgroundHeight; setDrawableBoundsInner(currentBackgroundDrawable, backgroundDrawableLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); - setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundDrawableLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); + if (forceMediaByGroup) { + setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundDrawableLeft + AndroidUtilities.dp(6), backgroundDrawableTop, backgroundDrawableRight - AndroidUtilities.dp(6), backgroundHeight); + } else { + setDrawableBoundsInner(currentBackgroundSelectedDrawable, backgroundDrawableLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); + } setDrawableBoundsInner(currentBackgroundShadowDrawable, backgroundDrawableLeft, backgroundDrawableTop, backgroundDrawableRight, backgroundHeight); } - if (!currentMessageObject.isOutOwner() && transitionParams.changePinnedBottomProgress != 1 && (!mediaBackground && !drawPinnedBottom)) { + if (!currentMessageObject.isOutOwner() && transitionParams.changePinnedBottomProgress != 1 && !mediaBackground && !drawPinnedBottom) { backgroundDrawableLeft -= AndroidUtilities.dp(6); backgroundDrawableRight += AndroidUtilities.dp(6); } @@ -9577,35 +9753,48 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (drawBackground && currentBackgroundDrawable != null && currentPosition == null) { + if (drawBackground && currentBackgroundDrawable != null && (currentPosition == null || isDrawSelectionBackground() && (currentMessageObject.isMusic() || currentMessageObject.isDocument()))) { if (isHighlightedAnimated) { currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundDrawable.draw(canvas); float alpha = highlightProgress >= 300 ? 1.0f : highlightProgress / 300.0f; + currentSelectedBackgroundAlpha = alpha; if (currentPosition == null) { currentBackgroundSelectedDrawable.setAlpha((int) (alphaInternal * alpha * 255)); currentBackgroundSelectedDrawable.draw(canvas); } - } else if (selectedBackgroundProgress != 0) { + } else if (selectedBackgroundProgress != 0 && !(currentMessagesGroup != null && currentMessagesGroup.isDocuments)) { currentBackgroundDrawable.draw(canvas); + currentSelectedBackgroundAlpha = selectedBackgroundProgress; currentBackgroundSelectedDrawable.setAlpha((int) (selectedBackgroundProgress * alphaInternal * 255)); currentBackgroundSelectedDrawable.draw(canvas); - currentBackgroundShadowDrawable = null; + if (currentBackgroundDrawable.getGradientShader() == null) { + currentBackgroundShadowDrawable = null; + } } else { - if (isDrawSelectionBackground() && (currentPosition == null || getBackground() != null)) { + if (isDrawSelectionBackground() && (currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument() || getBackground() != null)) { + if (currentPosition != null) { + canvas.save(); + canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); + } + currentSelectedBackgroundAlpha = 1f; currentBackgroundSelectedDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundSelectedDrawable.draw(canvas); + if (currentPosition != null) { + canvas.restore(); + } } else { + currentSelectedBackgroundAlpha = 0; currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundDrawable.draw(canvas); } } - if (currentBackgroundShadowDrawable != null && (currentPosition == null || currentPosition.flags != 0)) { + if (currentBackgroundShadowDrawable != null && currentPosition == null) { currentBackgroundShadowDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundShadowDrawable.draw(canvas); } - if (transitionParams.changePinnedBottomProgress != 1f) { + if (transitionParams.changePinnedBottomProgress != 1f && currentPosition == null) { if (currentMessageObject.isOutOwner()) { Theme.MessageDrawable drawable = Theme.chat_msgOutDrawable; @@ -9621,7 +9810,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate h = view.getMeasuredHeight(); } } - drawable.setTop((int) getY(), h, pinnedTop, pinnedBottom); + drawable.setTop((int) (getY() + parentViewTopOffset), h, pinnedTop, pinnedBottom); float alpha = !mediaBackground && !pinnedBottom ? transitionParams.changePinnedBottomProgress : (1f - transitionParams.changePinnedBottomProgress); drawable.setAlpha((int) (255 * alpha)); drawable.draw(canvas); @@ -9780,8 +9969,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate setDrawableBounds(Theme.chat_shareDrawable, sideStartX, sideStartY, AndroidUtilities.dp(32), AndroidUtilities.dp(32)); Theme.chat_shareDrawable.draw(canvas); if (drawSideButton == 2) { - setDrawableBounds(Theme.chat_goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); + if (currentMessageObject.isOutOwner()) { + setDrawableBounds(Theme.chat_goIconDrawable, sideStartX + AndroidUtilities.dp(10), sideStartY + AndroidUtilities.dp(9)); + canvas.save(); + canvas.scale(-1, 1, Theme.chat_goIconDrawable.getBounds().centerX(), Theme.chat_goIconDrawable.getBounds().centerY()); + } else { + setDrawableBounds(Theme.chat_goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); + } Theme.chat_goIconDrawable.draw(canvas); + if (currentMessageObject.isOutOwner()) { + canvas.restore(); + } } else { setDrawableBounds(Theme.chat_shareIconDrawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); Theme.chat_shareIconDrawable.draw(canvas); @@ -9806,21 +10004,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (mediaBackground) { replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); } else { - replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 12 : 18) + getExtraTextX(); + replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); } } replyStartY = AndroidUtilities.dp(12 + (drawForwardedName && forwardedNameLayout[0] != null ? 36 : 0) + (drawNameLayout && nameLayout != null ? 20 : 0)); } } - if (currentPosition == null) { + if (currentPosition == null && !transitionParams.animateBackgroundBoundsInner) { drawNamesLayout(canvas, 1f); } - if (!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject)) { + if (!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject) && !transitionParams.animateBackgroundBoundsInner) { drawOverlays(canvas); } if ((drawTime || !mediaBackground) && !forceNotDrawTime && !transitionParams.animateBackgroundBoundsInner) { - drawTime(canvas, 1f); + drawTime(canvas, 1f, false); } if ((controlsAlpha != 1.0f || timeAlpha != 1.0f) && currentMessageObject.type != 5) { @@ -9876,11 +10074,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return layoutWidth - backgroundWidth - (!mediaBackground ? 0 : AndroidUtilities.dp(9)); } else { int r = AndroidUtilities.dp((isChat && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (currentPosition.leftSpanOffset != 0) { r += (int) Math.ceil(currentPosition.leftSpanOffset / 1000.0f * getGroupPhotosWidth()); } } + if ((!mediaBackground && drawPinnedBottom)) { + r += AndroidUtilities.dp(6); + } return r; } } @@ -9890,6 +10091,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!mediaBackground && drawPinnedBottom && currentMessageObject.isOutOwner()) { right -= AndroidUtilities.dp(6); } + if (!mediaBackground && drawPinnedBottom && !currentMessageObject.isOutOwner()) { + right -= AndroidUtilities.dp(6); + } return getBackgroundDrawableLeft() + right; } @@ -9900,7 +10104,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate additionalTop -= AndroidUtilities.dp( 3); } } - return additionalTop + (drawPinnedTop || drawPinnedTop && drawPinnedBottom ? 0 : AndroidUtilities.dp(1)); + return additionalTop + (drawPinnedTop ? 0 : AndroidUtilities.dp(1)); } public int getBackgroundDrawableBottom() { @@ -9933,7 +10137,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundDrawable = Theme.chat_msgOutMediaDrawable; } } else { - if (!mediaBackground && !pinnedTop) { + if (!mediaBackground && !pinnedBottom) { currentBackgroundDrawable = Theme.chat_msgInDrawable; } else { currentBackgroundDrawable = Theme.chat_msgInMediaDrawable; @@ -9948,22 +10152,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate h = view.getMeasuredHeight(); } } - currentBackgroundDrawable.setTop(0, h, pinnedTop, pinnedBottom); - - Drawable currentBackgroundShadowDrawable = null; - - if (currentBackgroundDrawable != null) { - currentBackgroundShadowDrawable = currentBackgroundDrawable.getShadowDrawable(); - } - - if (currentBackgroundShadowDrawable != null) { - currentBackgroundShadowDrawable.setAlpha((int) (getAlpha() * 255)); - currentBackgroundShadowDrawable.setBounds(left, top, right, bottom); - currentBackgroundShadowDrawable.draw(canvas); - currentBackgroundShadowDrawable.setAlpha(255); - } if (currentBackgroundDrawable != null) { + currentBackgroundDrawable.setTop(0, h, pinnedTop, pinnedBottom); + Drawable currentBackgroundShadowDrawable = currentBackgroundDrawable.getShadowDrawable(); + if (currentBackgroundShadowDrawable != null) { + currentBackgroundShadowDrawable.setAlpha((int) (getAlpha() * 255)); + currentBackgroundShadowDrawable.setBounds(left, top, right, bottom); + currentBackgroundShadowDrawable.draw(canvas); + currentBackgroundShadowDrawable.setAlpha(255); + } currentBackgroundDrawable.setAlpha((int) (getAlpha() * 255)); currentBackgroundDrawable.setBounds(left, top, right, bottom); currentBackgroundDrawable.draw(canvas); @@ -9971,7 +10169,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - public boolean hasNameLayout() { return drawNameLayout && nameLayout != null || drawForwardedName && forwardedNameLayout[0] != null && forwardedNameLayout[1] != null && (currentPosition == null || currentPosition.minY == 0 && currentPosition.minX == 0) || @@ -10011,11 +10208,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.shouldDrawWithoutBackground()) { Theme.chat_namePaint.setColor(Theme.getColor(Theme.key_chat_stickerNameText)); - int backWidth; if (currentMessageObject.isOutOwner()) { nameX = AndroidUtilities.dp(28); } else { - nameX = backgroundDrawableLeft + backgroundDrawableRight + AndroidUtilities.dp(22); + nameX = backgroundDrawableLeft + transitionParams.deltaLeft + backgroundDrawableRight + AndroidUtilities.dp(22); } nameY = layoutHeight - AndroidUtilities.dp(38); float alphaProgress = currentMessageObject.isOut() && (checkBoxVisible || checkBoxAnimationInProgress) ? (1.0f - checkBoxAnimationProgress) : 1.0f; @@ -10038,12 +10234,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_systemDrawable.setAlpha(255); } else { if (mediaBackground || currentMessageObject.isOutOwner()) { - nameX = backgroundDrawableLeft + AndroidUtilities.dp(11) - nameOffsetX + getExtraTextX(); + nameX = backgroundDrawableLeft + transitionParams.deltaLeft + AndroidUtilities.dp(11) - nameOffsetX + getExtraTextX(); } else { - nameX = backgroundDrawableLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17) - nameOffsetX + getExtraTextX(); + nameX = backgroundDrawableLeft + transitionParams.deltaLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17) - nameOffsetX + getExtraTextX(); } if (currentUser != null) { - Theme.chat_namePaint.setColor(AvatarDrawable.getNameColorForId(currentUser.id)); + if (currentBackgroundDrawable.hasGradient()) { + Theme.chat_namePaint.setColor(Theme.getColor(Theme.key_chat_messageTextOut)); + } else { + Theme.chat_namePaint.setColor(AvatarDrawable.getNameColorForId(currentUser.id)); + } } else if (currentChat != null) { if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { Theme.chat_namePaint.setColor(Theme.changeColorAccent(AvatarDrawable.getNameColorForId(5))); @@ -10057,6 +10257,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } nameY = AndroidUtilities.dp(drawPinnedTop ? 9 : 10); } + if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { + nameX += currentMessagesGroup.transitionParams.offsetLeft; + nameY += currentMessagesGroup.transitionParams.offsetTop - getTranslationY(); + } + nameX += animationOffsetX; + nameY += transitionParams.deltaTop; float nx; if (transitionParams.animateSign) { nx = transitionParams.animateNameX + (nameX - transitionParams.animateNameX) * transitionParams.animateChangeProgress; @@ -10076,7 +10282,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_adminPaint.setColor(color); canvas.save(); float ax; - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { int dWidth = getGroupPhotosWidth(); int firstLineWidth = 0; for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { @@ -10124,7 +10330,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int backWidth = forwardedNameWidth + AndroidUtilities.dp(14); Theme.chat_systemDrawable.setColorFilter(Theme.colorFilter); - Theme.chat_systemDrawable.setBounds(forwardNameX - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), forwardNameX - AndroidUtilities.dp(7) + backWidth, forwardNameY + AndroidUtilities.dp(38)); + Theme.chat_systemDrawable.setBounds((int) forwardNameX - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameX - AndroidUtilities.dp(7) + backWidth, forwardNameY + AndroidUtilities.dp(38)); Theme.chat_systemDrawable.draw(canvas); } else { forwardNameY = AndroidUtilities.dp(10 + (drawNameLayout ? 19 : 0)); @@ -10144,7 +10350,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (mediaBackground) { forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(11) + getExtraTextX(); } else { - forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17) + getExtraTextX(); + forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 11 : 17) + getExtraTextX(); } } } @@ -10192,13 +10398,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (replyNameLayout != null) { + float replyStartX = this.replyStartX; + if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { + replyStartX += currentMessagesGroup.transitionParams.offsetLeft; + } + if (transitionParams.animateBackgroundBoundsInner) { + replyStartX += transitionParams.deltaLeft; + } if (currentMessageObject.shouldDrawWithoutBackground()) { Theme.chat_replyLinePaint.setColor(Theme.getColor(Theme.key_chat_stickerReplyLine)); Theme.chat_replyNamePaint.setColor(Theme.getColor(Theme.key_chat_stickerReplyNameText)); Theme.chat_replyTextPaint.setColor(Theme.getColor(Theme.key_chat_stickerReplyMessageText)); int backWidth = Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(14); Theme.chat_systemDrawable.setColorFilter(Theme.colorFilter); - Theme.chat_systemDrawable.setBounds(replyStartX - AndroidUtilities.dp(7), replyStartY - AndroidUtilities.dp(6), replyStartX - AndroidUtilities.dp(7) + backWidth, replyStartY + AndroidUtilities.dp(41)); + Theme.chat_systemDrawable.setBounds((int) replyStartX - AndroidUtilities.dp(7), replyStartY - AndroidUtilities.dp(6), (int) replyStartX - AndroidUtilities.dp(7) + backWidth, replyStartY + AndroidUtilities.dp(41)); Theme.chat_systemDrawable.draw(canvas); } else { if (currentMessageObject.isOutOwner()) { @@ -10283,11 +10496,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate checkBox.onAttachedToWindow(); } } - if (visible && photoCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) { - photoCheckBox = new CheckBoxBase(this, 21); - photoCheckBox.setUseDefaultCheck(true); + if (visible && mediaCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) { + mediaCheckBox = new CheckBoxBase(this, 21); + mediaCheckBox.setUseDefaultCheck(true); if (attachedToWindow) { - photoCheckBox.onAttachedToWindow(); + mediaCheckBox.onAttachedToWindow(); } } if (checkBoxVisible == visible) { @@ -10311,8 +10524,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (checkBox != null) { checkBox.setChecked(allChecked, animated); } - if (photoCheckBox != null) { - photoCheckBox.setChecked(checked, animated); + if (mediaCheckBox != null) { + mediaCheckBox.setChecked(checked, animated); } backgroundDrawable.setSelected(allChecked, animated); } @@ -10347,10 +10560,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (mediaBackground) { x = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); } else { - x = backgroundDrawableLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 12 : 18) + getExtraTextX(); + x = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); } int endX = x - getExtraTextX(); - if (currentMessagesGroup != null) { + if (currentMessagesGroup != null && !currentMessageObject.isMusic() && !currentMessageObject.isDocument()) { int dWidth = getGroupPhotosWidth(); if ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0) { endX += Math.ceil(currentPosition.pw / 1000.0f * dWidth); @@ -10397,7 +10610,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && currentPosition.minX == 0 && currentPosition.maxX == 0) { Theme.chat_instantViewPaint.setColor(Theme.getColor(Theme.key_chat_inPreviewInstantText)); boolean drawnAvatars = false; - int avatarsOffset = 0; + int avatarsOffset = 2; if (commentAvatarImages != null) { int toAdd = AndroidUtilities.dp(17); int ax = x + getExtraTextX(); @@ -10412,7 +10625,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } commentAvatarImages[a].draw(canvas); drawnAvatars = true; - avatarsOffset += a == 0 ? 2 : 17; + if (a != 0) { + avatarsOffset += 17; + } } } if (!mediaBackground || captionLayout != null) { @@ -10426,17 +10641,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (commentLayout != null && drawSideButton != 3) { Theme.chat_replyNamePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewInstantText : Theme.key_chat_inPreviewInstantText)); + commentX = x + AndroidUtilities.dp(33 + avatarsOffset); + if (drawCommentNumber) { + commentX += commentNumberWidth + AndroidUtilities.dp(4); + } + int prevAlpha = Theme.chat_replyNamePaint.getAlpha(); if (transitionParams.animateComments) { if (transitionParams.animateCommentsLayout != null) { canvas.save(); - Theme.chat_replyNamePaint.setAlpha((int) (255 * (1.0 - transitionParams.animateChangeProgress))); - canvas.translate(x + AndroidUtilities.dp(33 + avatarsOffset), y - AndroidUtilities.dp(0.1f) + (pinnedBottom ? AndroidUtilities.dp(2) : 0)); + Theme.chat_replyNamePaint.setAlpha((int) (prevAlpha * (1.0 - transitionParams.animateChangeProgress))); + float cx = transitionParams.animateCommentX + (commentX - transitionParams.animateCommentX) * transitionParams.animateChangeProgress; + canvas.translate(cx, y - AndroidUtilities.dp(0.1f) + (pinnedBottom ? AndroidUtilities.dp(2) : 0)); transitionParams.animateCommentsLayout.draw(canvas); canvas.restore(); } - Theme.chat_replyNamePaint.setAlpha((int) (255 * transitionParams.animateChangeProgress)); } - int prevAlpha = Theme.chat_replyNamePaint.getAlpha(); + canvas.save(); + canvas.translate(x + AndroidUtilities.dp(33 + avatarsOffset), y - AndroidUtilities.dp(0.1f) + (pinnedBottom ? AndroidUtilities.dp(2) : 0)); if (!currentMessageObject.isSent()) { Theme.chat_replyNamePaint.setAlpha(127); Theme.chat_commentArrowDrawable.setAlpha(127); @@ -10445,12 +10666,42 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_commentArrowDrawable.setAlpha(255); Theme.chat_commentDrawable.setAlpha(255); } - canvas.save(); - canvas.translate(x + AndroidUtilities.dp(33 + avatarsOffset), y - AndroidUtilities.dp(0.1f) + (pinnedBottom ? AndroidUtilities.dp(2) : 0)); + if (drawCommentNumber || transitionParams.animateComments && transitionParams.animateDrawCommentNumber) { + if (drawCommentNumber && transitionParams.animateComments) { + if (transitionParams.animateDrawCommentNumber) { + Theme.chat_replyNamePaint.setAlpha(prevAlpha); + } else { + Theme.chat_replyNamePaint.setAlpha((int) (prevAlpha * transitionParams.animateChangeProgress)); + } + } + commentNumberLayout.draw(canvas); + if (drawCommentNumber) { + canvas.translate(commentNumberWidth + AndroidUtilities.dp(4), 0); + } + } + if (transitionParams.animateComments && transitionParams.animateCommentsLayout != null) { + Theme.chat_replyNamePaint.setAlpha((int) (prevAlpha * transitionParams.animateChangeProgress)); + } else { + Theme.chat_replyNamePaint.setAlpha(prevAlpha); + } commentLayout.draw(canvas); canvas.restore(); commentUnreadX = x + commentWidth + AndroidUtilities.dp(33 + avatarsOffset) + AndroidUtilities.dp(9); - if (commentDrawUnread = currentMessageObject.hasReplies() && currentMessageObject.messageOwner.replies.read_max_id != 0 && currentMessageObject.messageOwner.replies.read_max_id < currentMessageObject.messageOwner.replies.max_id) { + if (drawCommentNumber) { + commentUnreadX += commentNumberWidth + AndroidUtilities.dp(4); + } + TLRPC.TL_messageReplies replies = null; + if (currentMessagesGroup != null && !currentMessagesGroup.messages.isEmpty()) { + MessageObject messageObject = currentMessagesGroup.messages.get(0); + if (messageObject.hasReplies()) { + replies = messageObject.messageOwner.replies; + } + } else { + if (currentMessageObject.hasReplies()) { + replies = currentMessageObject.messageOwner.replies; + } + } + if (commentDrawUnread = (replies != null && replies.read_max_id != 0 && replies.read_max_id < replies.max_id)) { int color = Theme.getColor(Theme.key_chat_inInstant); Theme.chat_docBackPaint.setColor(color); int unreadX; @@ -10597,10 +10848,59 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean shouldDrawTimeOnMedia() { + if (overideShouldDrawTimeOnMedia != 0) { + return overideShouldDrawTimeOnMedia == 1; + } return mediaBackground && captionLayout == null || isMedia && drawCommentButton && !isRepliesChat; } - public void drawTime(Canvas canvas, float alpha) { + public void drawTime(Canvas canvas, float alpha, boolean fromParent) { + for (int i = 0; i < 2; i++) { + float curentAplha = alpha; + if (i == 0 && isDrawSelectionBackground() && currentSelectedBackgroundAlpha == 1f && !shouldDrawTimeOnMedia()) { + continue; + } else if (i == 1 && ((!isDrawSelectionBackground() && currentSelectedBackgroundAlpha == 0) || shouldDrawTimeOnMedia())) { + break; + } + boolean drawSelectionBackground = i == 1; + if (i == 1) { + curentAplha *= currentSelectedBackgroundAlpha; + } else if (!shouldDrawTimeOnMedia()){ + curentAplha *= (1f - currentSelectedBackgroundAlpha); + } + if (transitionParams.animateShouldDrawTimeOnMedia && transitionParams.animateChangeProgress != 1f) { + if (shouldDrawTimeOnMedia()) { + overideShouldDrawTimeOnMedia = 1; + drawTimeInternal(canvas, curentAplha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); + overideShouldDrawTimeOnMedia = 2; + drawTimeInternal(canvas, curentAplha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); + } else { + overideShouldDrawTimeOnMedia = 2; + drawTimeInternal(canvas, curentAplha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); + overideShouldDrawTimeOnMedia = 1; + drawTimeInternal(canvas, curentAplha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); + } + overideShouldDrawTimeOnMedia = 0; + } else { + float timeX; + float timeWidth; + if (transitionParams.shouldAnimateTimeX) { + timeX = this.timeX * transitionParams.animateChangeProgress + transitionParams.animateFromTimeX * (1f - transitionParams.animateChangeProgress); + timeWidth = this.timeWidth * transitionParams.animateChangeProgress + transitionParams.animateTimeWidth * (1f - transitionParams.animateChangeProgress); + } else { + timeX = this.timeX + transitionParams.deltaRight; + timeWidth = this.timeWidth; + } + drawTimeInternal(canvas, curentAplha, fromParent, timeX, timeLayout, timeWidth, drawSelectionBackground); + } + } + + if (transitionParams.animateBackgroundBoundsInner) { + drawOverlays(canvas); + } + } + + private void drawTimeInternal(Canvas canvas, float alpha, boolean fromParent, float timeX, StaticLayout timeLayout, float timeWidth, boolean drawSelectionBackground) { if ((!drawTime || groupPhotoInvisible) && shouldDrawTimeOnMedia() || timeLayout == null || (currentMessageObject.deleted && currentPosition != null) || currentMessageObject.type == 16) { return; } @@ -10615,9 +10915,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { if (currentMessageObject.isOutOwner()) { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(drawSelectionBackground ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); } else { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(drawSelectionBackground ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); } } } @@ -10627,18 +10927,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (alpha != 1f) { Theme.chat_timePaint.setAlpha((int) (Theme.chat_timePaint.getAlpha() * alpha)); } - if (drawPinnedBottom) { + canvas.save(); + if (drawPinnedBottom && !shouldDrawTimeOnMedia()) { canvas.translate(0, AndroidUtilities.dp(2)); } - float timeX = this.timeX + transitionParams.deltaRight; boolean bigRadius = false; float layoutHeight = this.layoutHeight + transitionParams.deltaBottom; + float timeTitleTimeX = (transitionParams.shouldAnimateTimeX ? this.timeX : timeX) + transitionParams.deltaRight; if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { layoutHeight -= getTranslationY(); timeX += currentMessagesGroup.transitionParams.offsetRight; + timeTitleTimeX += currentMessagesGroup.transitionParams.offsetRight; + } + if (drawPinnedBottom && shouldDrawTimeOnMedia()) { + layoutHeight += AndroidUtilities.dp(1); } if (transitionParams.animateBackgroundBoundsInner) { timeX += animationOffsetX; + timeTitleTimeX += animationOffsetX; } int timeYOffset; if (shouldDrawTimeOnMedia()) { @@ -10669,320 +10975,642 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.drawRoundRect(rect, r, r, paint); paint.setAlpha(oldAlpha); - int additionalX = (int) (-timeLayout.getLineLeft(0)); - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || repliesLayout != null) { - additionalX += (int) (timeWidth - timeLayout.getLineWidth(0)); + float additionalX = -timeLayout.getLineLeft(0); + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || repliesLayout != null || isPinned) { + additionalX += this.timeWidth - timeLayout.getLineWidth(0); - if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { - if (!currentMessageObject.isOutOwner()) { - setDrawableBounds(Theme.chat_msgMediaClockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), timeY - AndroidUtilities.dp(9.0f) - Theme.chat_msgMediaClockDrawable.getIntrinsicHeight()); - Theme.chat_msgMediaClockDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgMediaClockDrawable.draw(canvas); - Theme.chat_msgMediaClockDrawable.setAlpha(255); - } - } else if (currentMessageObject.isSendError()) { - if (!currentMessageObject.isOutOwner()) { - float x = timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)); - float y = timeY - AndroidUtilities.dp(21.5f); - rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); - oldAlpha = Theme.chat_msgErrorPaint.getAlpha(); - Theme.chat_msgErrorPaint.setAlpha((int) (oldAlpha * alpha)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); - Theme.chat_msgErrorPaint.setAlpha(oldAlpha); - setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); - Theme.chat_msgErrorDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgErrorDrawable.draw(canvas); - Theme.chat_msgErrorDrawable.setAlpha(255); - } + int currentStatus = transitionParams.createStatusDrawableParams(); + if (transitionParams.lastStatusDrawableParams >= 0 && transitionParams.lastStatusDrawableParams != currentStatus && !statusDrawableAnimationInProgress) { + createStatusDrawableAnimator(transitionParams.lastStatusDrawableParams, currentStatus, fromParent); + } + if (statusDrawableAnimationInProgress) { + currentStatus = animateToStatusDrawableParams; + } + + boolean drawClock = (currentStatus & 4) != 0; + boolean drawError = (currentStatus & 8) != 0; + + if (statusDrawableAnimationInProgress) { + boolean outDrawClock = (animateFromStatusDrawableParams & 4) != 0; + boolean outDrawError = (animateFromStatusDrawableParams & 8) != 0; + drawViewsAndRepliesLayout(canvas, outDrawClock, outDrawError, layoutHeight, alpha, timeYOffset, timeX, 1f - statusDrawableProgress, drawSelectionBackground); + drawViewsAndRepliesLayout(canvas, drawClock, drawError, layoutHeight, alpha, timeYOffset, timeX, statusDrawableProgress, drawSelectionBackground); } else { - int offsetX = 0; - if (repliesLayout != null) { - Drawable repliesDrawable; - if (currentMessageObject.shouldDrawWithoutBackground()) { - repliesDrawable = Theme.chat_msgStickerRepliesDrawable; - } else { - repliesDrawable = Theme.chat_msgMediaRepliesDrawable; - } - oldAlpha = ((BitmapDrawable) repliesDrawable).getPaint().getAlpha(); - repliesDrawable.setAlpha((int) (timeAlpha * oldAlpha * alpha)); - setDrawableBounds(repliesDrawable, timeX, timeY - AndroidUtilities.dp(7.5f) - timeLayout.getHeight()); - repliesDrawable.draw(canvas); - repliesDrawable.setAlpha(oldAlpha); + drawViewsAndRepliesLayout(canvas, drawClock, drawError, layoutHeight, alpha, timeYOffset, timeX, 1f, drawSelectionBackground); + } - if (transitionParams.animateReplies) { - if (transitionParams.animateRepliesLayout != null) { - canvas.save(); - Theme.chat_timePaint.setAlpha((int) (255 * (1.0 - transitionParams.animateChangeProgress))); - canvas.translate(timeX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); - transitionParams.animateRepliesLayout.draw(canvas); - canvas.restore(); - } - Theme.chat_timePaint.setAlpha((int) (255 * transitionParams.animateChangeProgress)); - } - canvas.save(); - canvas.translate(timeX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); - repliesLayout.draw(canvas); - canvas.restore(); - offsetX = repliesDrawable.getIntrinsicWidth() + repliesTextWidth + AndroidUtilities.dp(10); - } - if (viewsLayout != null) { - Drawable viewsDrawable; - if (currentMessageObject.shouldDrawWithoutBackground()) { - viewsDrawable = Theme.chat_msgStickerViewsDrawable; - } else { - viewsDrawable = Theme.chat_msgMediaViewsDrawable; - } - oldAlpha = ((BitmapDrawable) viewsDrawable).getPaint().getAlpha(); - viewsDrawable.setAlpha((int) (timeAlpha * oldAlpha * alpha)); - setDrawableBounds(viewsDrawable, timeX + offsetX, timeY - AndroidUtilities.dp(5.5f) - timeLayout.getHeight()); - viewsDrawable.draw(canvas); - viewsDrawable.setAlpha(oldAlpha); + transitionParams.lastStatusDrawableParams = transitionParams.createStatusDrawableParams(); - canvas.save(); - canvas.translate(timeX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) + offsetX, timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); - viewsLayout.draw(canvas); - canvas.restore(); - } + if (drawClock && fromParent && getParent() != null) { + ((View)getParent()).invalidate(); } } canvas.save(); - canvas.translate(timeX + additionalX, timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); + canvas.translate(timeTitleTimeX + additionalX, timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); timeLayout.draw(canvas); canvas.restore(); Theme.chat_timePaint.setAlpha(255); } else { timeYOffset = -(drawCommentButton ? AndroidUtilities.dp(43) : 0); - int additionalX = (int) (-timeLayout.getLineLeft(0)); - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || repliesLayout != null) { - additionalX += (int) (timeWidth - timeLayout.getLineWidth(0)); + float additionalX = -timeLayout.getLineLeft(0); + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || (repliesLayout != null || transitionParams.animateReplies) || (isPinned || transitionParams.animatePinned)) { + additionalX += this.timeWidth - timeLayout.getLineWidth(0); - if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { - if (!currentMessageObject.isOutOwner()) { - Drawable clockDrawable = isDrawSelectionBackground() ? Theme.chat_msgInSelectedClockDrawable : Theme.chat_msgInClockDrawable; - setDrawableBounds(clockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9.5f : 8.5f) - clockDrawable.getIntrinsicHeight() + timeYOffset); - clockDrawable.setAlpha((int) (255 * alpha)); - clockDrawable.draw(canvas); - clockDrawable.setAlpha(255); - } - } else if (currentMessageObject.isSendError()) { - if (!currentMessageObject.isOutOwner()) { - float x = timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)); - float y = layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 21.5f : 20.5f) + timeYOffset; - rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); - int oldAlpha = Theme.chat_msgErrorPaint.getAlpha(); - Theme.chat_msgErrorPaint.setAlpha((int) (255 * alpha)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); - Theme.chat_msgErrorPaint.setAlpha(oldAlpha); - setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); - Theme.chat_msgErrorDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgErrorDrawable.draw(canvas); - Theme.chat_msgErrorDrawable.setAlpha(255); - } + int currentStatus = transitionParams.createStatusDrawableParams(); + if (transitionParams.lastStatusDrawableParams >= 0 && transitionParams.lastStatusDrawableParams != currentStatus && !statusDrawableAnimationInProgress) { + createStatusDrawableAnimator(transitionParams.lastStatusDrawableParams, currentStatus, fromParent); + } + if (statusDrawableAnimationInProgress) { + currentStatus = animateToStatusDrawableParams; + } + + boolean drawClock = (currentStatus & 4) != 0; + boolean drawError = (currentStatus & 8) != 0; + + if (statusDrawableAnimationInProgress) { + boolean outDrawClock = (animateFromStatusDrawableParams & 4) != 0; + boolean outDrawError = (animateFromStatusDrawableParams & 8) != 0; + drawViewsAndRepliesLayout(canvas, outDrawClock, outDrawError, layoutHeight, alpha, timeYOffset, timeX, 1f - statusDrawableProgress, drawSelectionBackground); + drawViewsAndRepliesLayout(canvas, drawClock, drawError, layoutHeight, alpha, timeYOffset, timeX, statusDrawableProgress, drawSelectionBackground); } else { - int offsetX = 0; - if (repliesLayout != null) { - Drawable repliesDrawable; - if (!currentMessageObject.isOutOwner()) { - repliesDrawable = isDrawSelectionBackground() ? Theme.chat_msgInRepliesSelectedDrawable : Theme.chat_msgInRepliesDrawable; - } else { - repliesDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutRepliesSelectedDrawable : Theme.chat_msgOutRepliesDrawable; - } - setDrawableBounds(repliesDrawable, timeX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); - repliesDrawable.setAlpha((int) (255 * alpha)); - repliesDrawable.draw(canvas); - repliesDrawable.setAlpha(255); + drawViewsAndRepliesLayout(canvas, drawClock, drawError, layoutHeight, alpha, timeYOffset, timeX, 1f, drawSelectionBackground); + } - if (transitionParams.animateReplies) { - if (transitionParams.animateRepliesLayout != null) { - canvas.save(); - Theme.chat_timePaint.setAlpha((int) (255 * (1.0 - transitionParams.animateChangeProgress))); - canvas.translate(timeX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); - transitionParams.animateRepliesLayout.draw(canvas); - canvas.restore(); - } - Theme.chat_timePaint.setAlpha((int) (255 * transitionParams.animateChangeProgress)); - } - canvas.save(); - canvas.translate(timeX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); - repliesLayout.draw(canvas); - canvas.restore(); - offsetX = repliesDrawable.getIntrinsicWidth() + repliesTextWidth + AndroidUtilities.dp(10); - } - if (viewsLayout != null) { - Drawable viewsDrawable; - if (!currentMessageObject.isOutOwner()) { - viewsDrawable = isDrawSelectionBackground() ? Theme.chat_msgInViewsSelectedDrawable : Theme.chat_msgInViewsDrawable; - } else { - viewsDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutViewsSelectedDrawable : Theme.chat_msgOutViewsDrawable; - } - setDrawableBounds(viewsDrawable, timeX + offsetX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 5.5f : 4.5f) - timeLayout.getHeight() + timeYOffset); - viewsDrawable.setAlpha((int) (255 * alpha)); - viewsDrawable.draw(canvas); - viewsDrawable.setAlpha(255); + transitionParams.lastStatusDrawableParams = transitionParams.createStatusDrawableParams(); - canvas.save(); - canvas.translate(timeX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) + offsetX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); - viewsLayout.draw(canvas); - canvas.restore(); - } + if (drawClock && fromParent && getParent() != null) { + ((View)getParent()).invalidate(); } } - canvas.save(); - canvas.translate(timeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); if (transitionParams.animateEditedEnter && transitionParams.animateChangeProgress != 1f) { - int oldAlpha = Theme.chat_timePaint.getAlpha(); - Theme.chat_timePaint.setAlpha((int) (oldAlpha * transitionParams.animateChangeProgress)); - transitionParams.animateEditedLayout.draw(canvas); - Theme.chat_timePaint.setAlpha(oldAlpha); - transitionParams.animateTimeLayout.draw(canvas); + if (transitionParams.animateEditedLayout != null) { + canvas.translate(timeTitleTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); + int oldAlpha = Theme.chat_timePaint.getAlpha(); + Theme.chat_timePaint.setAlpha((int) (oldAlpha * transitionParams.animateChangeProgress)); + transitionParams.animateEditedLayout.draw(canvas); + Theme.chat_timePaint.setAlpha(oldAlpha); + transitionParams.animateTimeLayout.draw(canvas); + } else { + int oldAlpha = Theme.chat_timePaint.getAlpha(); + canvas.save(); + canvas.translate(transitionParams.animateFromTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); + Theme.chat_timePaint.setAlpha((int) (oldAlpha * (1f - transitionParams.animateChangeProgress))); + transitionParams.animateTimeLayout.draw(canvas); + canvas.restore(); + + canvas.translate(timeTitleTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); + Theme.chat_timePaint.setAlpha((int) (oldAlpha * (transitionParams.animateChangeProgress))); + timeLayout.draw(canvas); + Theme.chat_timePaint.setAlpha(oldAlpha); + } } else { + canvas.translate(timeTitleTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); timeLayout.draw(canvas); } canvas.restore(); } if (currentMessageObject.isOutOwner()) { - boolean drawCheck1 = false; - boolean drawCheck2 = false; - boolean drawClock = false; - boolean drawError = false; - boolean isBroadcast = (int) (currentMessageObject.getDialogId() >> 32) == 1; - - if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { - drawCheck1 = false; - drawCheck2 = false; - drawClock = true; - drawError = false; - } else if (currentMessageObject.isSendError()) { - drawCheck1 = false; - drawCheck2 = false; - drawClock = false; - drawError = true; - } else if (currentMessageObject.isSent()) { - if (!currentMessageObject.scheduled && !currentMessageObject.isUnread()) { - drawCheck1 = true; - } else { - drawCheck1 = false; - } - drawCheck2 = true; - drawClock = false; - drawError = false; + int currentStatus = transitionParams.createStatusDrawableParams(); + if (transitionParams.lastStatusDrawableParams >= 0 && transitionParams.lastStatusDrawableParams != currentStatus && !statusDrawableAnimationInProgress) { + createStatusDrawableAnimator(transitionParams.lastStatusDrawableParams, currentStatus, fromParent); } - - if (drawClock) { - if (shouldDrawTimeOnMedia()) { - if (currentMessageObject.shouldDrawWithoutBackground()) { - Theme.chat_msgStickerClockDrawable.setAlpha((int) (255 * timeAlpha * alpha)); - setDrawableBounds(Theme.chat_msgStickerClockDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 24 : 22) - Theme.chat_msgStickerClockDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgStickerClockDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgStickerClockDrawable.draw(canvas); - Theme.chat_msgStickerClockDrawable.setAlpha(255); - } else { - setDrawableBounds(Theme.chat_msgMediaClockDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 24 : 22) - Theme.chat_msgMediaClockDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgMediaClockDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgMediaClockDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgMediaClockDrawable.draw(canvas); - Theme.chat_msgMediaClockDrawable.setAlpha(255); - } - } else { - setDrawableBounds(Theme.chat_msgOutClockDrawable, layoutWidth - AndroidUtilities.dp(18.5f) - Theme.chat_msgOutClockDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.5f) - Theme.chat_msgOutClockDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgOutClockDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgOutClockDrawable.draw(canvas); - Theme.chat_msgOutClockDrawable.setAlpha(255); - } + if (statusDrawableAnimationInProgress) { + currentStatus = animateToStatusDrawableParams; } - - if (isBroadcast) { - if (drawCheck1 || drawCheck2) { - if (shouldDrawTimeOnMedia()) { - setDrawableBounds(Theme.chat_msgBroadcastMediaDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 26 : 24) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(14.0f) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgBroadcastMediaDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgBroadcastMediaDrawable.draw(canvas); - Theme.chat_msgBroadcastMediaDrawable.setAlpha(255); - } else { - setDrawableBounds(Theme.chat_msgBroadcastDrawable, layoutWidth - AndroidUtilities.dp(20.5f) - Theme.chat_msgBroadcastDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - Theme.chat_msgBroadcastDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgBroadcastDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgBroadcastDrawable.draw(canvas); - Theme.chat_msgBroadcastDrawable.setAlpha(255); - } + boolean drawCheck1 = (currentStatus & 1) != 0; + boolean drawCheck2 = (currentStatus & 2) != 0; + boolean drawClock = (currentStatus & 4) != 0; + boolean drawError = (currentStatus & 8) != 0; + boolean isBroadcast = (currentStatus & 16) != 0; + if (statusDrawableAnimationInProgress) { + boolean outDrawCheck1 = (animateFromStatusDrawableParams & 1) != 0; + boolean outDrawCheck2 = (animateFromStatusDrawableParams & 2) != 0; + boolean outDrawClock = (animateFromStatusDrawableParams & 4) != 0; + boolean outDrawError = (animateFromStatusDrawableParams & 8) != 0; + boolean outIsBroadcast = (animateFromStatusDrawableParams & 16) != 0; + if (!outDrawClock && !isBroadcast && !outIsBroadcast && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1) { + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, true, drawSelectionBackground); + } else { + drawStatusDrawable(canvas, outDrawCheck1, outDrawCheck2, outDrawClock, outDrawError, outIsBroadcast, alpha, bigRadius, timeYOffset, layoutHeight,1f - statusDrawableProgress, false, drawSelectionBackground); + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, false, drawSelectionBackground); } } else { - if (drawCheck2) { - if (shouldDrawTimeOnMedia()) { - if (currentMessageObject.shouldDrawWithoutBackground()) { - if (drawCheck1) { - setDrawableBounds(Theme.chat_msgStickerCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicHeight() + timeYOffset); - } else { - setDrawableBounds(Theme.chat_msgStickerCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicHeight() + timeYOffset); - } - Theme.chat_msgStickerCheckDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgStickerCheckDrawable.draw(canvas); - Theme.chat_msgStickerCheckDrawable.setAlpha(255); - } else { - if (drawCheck1) { - setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); - } else { - setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); - } - Theme.chat_msgMediaCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); - Theme.chat_msgMediaCheckDrawable.draw(canvas); - Theme.chat_msgMediaCheckDrawable.setAlpha(255); - } - } else { - Drawable drawable; - if (drawCheck1) { - drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckReadSelectedDrawable : Theme.chat_msgOutCheckReadDrawable; - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - } else { - drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - } - drawable.setAlpha((int) (255 * alpha)); - drawable.draw(canvas); - drawable.setAlpha(255); - } - } - if (drawCheck1) { - if (shouldDrawTimeOnMedia()) { - if (currentMessageObject.shouldDrawWithoutBackground()) { - setDrawableBounds(Theme.chat_msgStickerHalfCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgStickerHalfCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgStickerHalfCheckDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgStickerHalfCheckDrawable.setAlpha((int) (255 * alpha)); - Theme.chat_msgStickerHalfCheckDrawable.draw(canvas); - Theme.chat_msgStickerHalfCheckDrawable.setAlpha(255); - } else { - setDrawableBounds(Theme.chat_msgMediaHalfCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaHalfCheckDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(13.5f) - Theme.chat_msgMediaHalfCheckDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgMediaHalfCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); - Theme.chat_msgMediaHalfCheckDrawable.draw(canvas); - Theme.chat_msgMediaHalfCheckDrawable.setAlpha(255); - } - } else { - Drawable drawable = isDrawSelectionBackground() ? Theme.chat_msgOutHalfCheckSelectedDrawable : Theme.chat_msgOutHalfCheckDrawable; - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - drawable.setAlpha((int) (255 * alpha)); - drawable.draw(canvas); - drawable.setAlpha(255); - } + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, 1, false, drawSelectionBackground); + } + transitionParams.lastStatusDrawableParams = transitionParams.createStatusDrawableParams(); + if (fromParent && drawClock && getParent() != null) { + ((View) getParent()).invalidate(); + } + } + canvas.restore(); + } + + private void createStatusDrawableAnimator(int lastStatusDrawableParams, int currentStatus, boolean fromParent) { + boolean drawCheck1 = (currentStatus & 1) != 0; + boolean drawCheck2 = (currentStatus & 2) != 0; + boolean isBroadcast = (currentStatus & 16) != 0; + + boolean outDrawCheck1 = (lastStatusDrawableParams & 1) != 0; + boolean outDrawCheck2 = (lastStatusDrawableParams & 2) != 0; + boolean outDrawClock = (lastStatusDrawableParams & 4) != 0; + boolean outIsBroadcast = (lastStatusDrawableParams & 16) != 0; + + boolean moveCheckTransition = !outDrawClock && !isBroadcast && !outIsBroadcast && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1; + + if (transitionParams.messageEntering && !moveCheckTransition) { + return; + } + statusDrawableProgress = 0f; + statusDrawableAnimator = ValueAnimator.ofFloat(0,1f); + if (moveCheckTransition) { + statusDrawableAnimator.setDuration(220); + } else { + statusDrawableAnimator.setDuration(150); + } + statusDrawableAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animateFromStatusDrawableParams = lastStatusDrawableParams; + animateToStatusDrawableParams = currentStatus; + statusDrawableAnimator.addUpdateListener(valueAnimator -> { + statusDrawableProgress = (float) valueAnimator.getAnimatedValue(); + invalidate(); + if (fromParent && getParent() != null) { + ((View) getParent()).invalidate(); + } + }); + statusDrawableAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + int currentStatus = transitionParams.createStatusDrawableParams(); + if (animateToStatusDrawableParams != currentStatus) { + createStatusDrawableAnimator(animateToStatusDrawableParams, currentStatus, fromParent); + } else { + statusDrawableAnimationInProgress = false; + transitionParams.lastStatusDrawableParams = animateToStatusDrawableParams; } } - if (drawError) { - int x; - float y; + }); + statusDrawableAnimationInProgress = true; + statusDrawableAnimator.start(); + + } + + private void drawViewsAndRepliesLayout(Canvas canvas, boolean drawTime, boolean drawError, float layoutHeight, float alpha, float timeYOffset, float timeX, float progress, boolean drawSelectionBackground) { + boolean useScale = progress != 1f; + float scale = 0.5f + 0.5f * progress; + alpha *= progress; + if (drawTime) { + if (!currentMessageObject.isOutOwner()) { + Drawable clockDrawable; if (shouldDrawTimeOnMedia()) { - x = layoutWidth - AndroidUtilities.dp(34.5f); - y = layoutHeight - AndroidUtilities.dp(26.5f) + timeYOffset; + clockDrawable = Theme.chat_msgMediaClockDrawable; } else { - x = layoutWidth - AndroidUtilities.dp(32); - y = layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 22 : 21) + timeYOffset; + clockDrawable = drawSelectionBackground ? Theme.chat_msgInSelectedClockDrawable : Theme.chat_msgInClockDrawable; } + float timeY = shouldDrawTimeOnMedia() ? photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(9.0f) : layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9.5f : 8.5f) + timeYOffset; + setDrawableBounds(clockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), timeY - clockDrawable.getIntrinsicHeight()); + clockDrawable.setAlpha((int) (255 * alpha)); + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, clockDrawable.getBounds().centerX(), clockDrawable.getBounds().centerY()); + } + clockDrawable.draw(canvas); + clockDrawable.setAlpha(255); + invalidate(); + if (useScale) { + canvas.restore(); + } + } + } else if (drawError) { + if (!currentMessageObject.isOutOwner()) { + float x = timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)); + float y = shouldDrawTimeOnMedia() ? photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(21.5f) : layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 21.5f : 20.5f) + timeYOffset; rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); int oldAlpha = Theme.chat_msgErrorPaint.getAlpha(); - Theme.chat_msgErrorPaint.setAlpha((int) (oldAlpha * alpha)); + Theme.chat_msgErrorPaint.setAlpha((int) (255 * alpha)); + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, rect.centerX(), rect.centerY()); + } canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); Theme.chat_msgErrorPaint.setAlpha(oldAlpha); setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); Theme.chat_msgErrorDrawable.setAlpha((int) (255 * alpha)); Theme.chat_msgErrorDrawable.draw(canvas); Theme.chat_msgErrorDrawable.setAlpha(255); + if (useScale) { + canvas.restore(); + } + } + } else { + float offsetX = 0; + int timeAlpha = Theme.chat_timePaint.getAlpha(); + float timeY = shouldDrawTimeOnMedia() ? photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight() : layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset; + if (repliesLayout != null || transitionParams.animateReplies) { + float repliesX = (transitionParams.shouldAnimateTimeX ? this.timeX : timeX) + offsetX; + boolean inAnimation = transitionParams.animateReplies && transitionParams.animateRepliesLayout == null && repliesLayout != null; + boolean outAnimation = transitionParams.animateReplies && transitionParams.animateRepliesLayout != null && repliesLayout == null; + boolean replaceAnimation = transitionParams.animateReplies && transitionParams.animateRepliesLayout != null && repliesLayout != null; + if (transitionParams.shouldAnimateTimeX && !inAnimation) { + if (outAnimation) { + repliesX = transitionParams.animateFromTimeXReplies; + } else { + repliesX = transitionParams.animateFromTimeXReplies * (1f - transitionParams.animateChangeProgress) + repliesX * transitionParams.animateChangeProgress; + } + } else { + repliesX += transitionParams.deltaRight; + } + if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { + repliesX += currentMessagesGroup.transitionParams.offsetRight; + } + if (transitionParams.animateBackgroundBoundsInner) { + repliesX += animationOffsetX; + } + Drawable repliesDrawable; + if (shouldDrawTimeOnMedia()) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + repliesDrawable = Theme.chat_msgStickerRepliesDrawable; + } else { + repliesDrawable = Theme.chat_msgMediaRepliesDrawable; + } + } else { + if (!currentMessageObject.isOutOwner()) { + repliesDrawable = drawSelectionBackground ? Theme.chat_msgInRepliesSelectedDrawable : Theme.chat_msgInRepliesDrawable; + } else { + repliesDrawable = drawSelectionBackground ? Theme.chat_msgOutRepliesSelectedDrawable : Theme.chat_msgOutRepliesDrawable; + } + } + setDrawableBounds(repliesDrawable, repliesX, timeY); + float repliesAlpha = alpha; + if (inAnimation) { + repliesAlpha *= transitionParams.animateChangeProgress; + } else if (outAnimation) { + repliesAlpha *= (1f - transitionParams.animateChangeProgress); + } + repliesDrawable.setAlpha((int) (255 * repliesAlpha)); + if (useScale) { + canvas.save(); + float cx = repliesX + (repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) + repliesTextWidth) / 2f; + canvas.scale(scale, scale, cx, repliesDrawable.getBounds().centerY()); + } + repliesDrawable.draw(canvas); + repliesDrawable.setAlpha(255); + + if (transitionParams.animateReplies) { + if (replaceAnimation) { + canvas.save(); + Theme.chat_timePaint.setAlpha((int) (timeAlpha * (1.0 - transitionParams.animateChangeProgress))); + canvas.translate(repliesX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) , timeY); + transitionParams.animateRepliesLayout.draw(canvas); + canvas.restore(); + } + Theme.chat_timePaint.setAlpha((int) (timeAlpha * repliesAlpha)); + } + canvas.save(); + canvas.translate(repliesX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), timeY); + if (repliesLayout != null) { + repliesLayout.draw(canvas); + } else if (transitionParams.animateRepliesLayout != null) { + transitionParams.animateRepliesLayout.draw(canvas); + } + canvas.restore(); + if (repliesLayout != null) { + offsetX += repliesDrawable.getIntrinsicWidth() + repliesTextWidth + AndroidUtilities.dp(10); + } + + if (useScale) { + canvas.restore(); + float cx = (repliesX + repliesDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) + repliesTextWidth - repliesX) / 2f; + canvas.scale(scale, scale, cx, repliesDrawable.getBounds().centerY()); + } + + if (transitionParams.animateReplies) { + Theme.chat_timePaint.setAlpha(timeAlpha); + } + transitionParams.lastTimeXReplies = repliesX; + } + if (viewsLayout != null) { + float viewsX = (transitionParams.shouldAnimateTimeX ? this.timeX : timeX) + offsetX; + if (transitionParams.shouldAnimateTimeX) { + viewsX = transitionParams.animateFromTimeXViews * (1f - transitionParams.animateChangeProgress) + viewsX * transitionParams.animateChangeProgress; + } else { + viewsX += transitionParams.deltaRight; + } + if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { + viewsX += currentMessagesGroup.transitionParams.offsetRight; + } + if (transitionParams.animateBackgroundBoundsInner) { + viewsX += animationOffsetX; + } + Drawable viewsDrawable; + if (shouldDrawTimeOnMedia()) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + viewsDrawable = Theme.chat_msgStickerViewsDrawable; + } else { + viewsDrawable = Theme.chat_msgMediaViewsDrawable; + } + } else { + if (!currentMessageObject.isOutOwner()) { + viewsDrawable = drawSelectionBackground ? Theme.chat_msgInViewsSelectedDrawable : Theme.chat_msgInViewsDrawable; + } else { + viewsDrawable = drawSelectionBackground ? Theme.chat_msgOutViewsSelectedDrawable : Theme.chat_msgOutViewsDrawable; + } + } + float y = shouldDrawTimeOnMedia() ? photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(5.5f) - timeLayout.getHeight() : layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 5.5f : 4.5f) - timeLayout.getHeight() + timeYOffset; + setDrawableBounds(viewsDrawable, viewsX, y); + if (useScale) { + canvas.save(); + float cx = viewsX + (viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3) + viewsTextWidth) / 2f; + canvas.scale(scale, scale, cx, viewsDrawable.getBounds().centerY()); + } + viewsDrawable.setAlpha((int) (255 * alpha)); + viewsDrawable.draw(canvas); + viewsDrawable.setAlpha(255); + + if (transitionParams.animateViewsLayout != null) { + canvas.save(); + Theme.chat_timePaint.setAlpha((int) (timeAlpha * (1.0 - transitionParams.animateChangeProgress))); + canvas.translate(viewsX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), timeY); + transitionParams.animateViewsLayout.draw(canvas); + canvas.restore(); + Theme.chat_timePaint.setAlpha((int) (timeAlpha * transitionParams.animateChangeProgress)); + } + + canvas.save(); + canvas.translate(viewsX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), timeY); + viewsLayout.draw(canvas); + canvas.restore(); + if (useScale) { + canvas.restore(); + } + + offsetX += viewsTextWidth + Theme.chat_msgInViewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); + + if (transitionParams.animateViewsLayout != null) { + Theme.chat_timePaint.setAlpha(timeAlpha); + } + transitionParams.lastTimeXViews = viewsX; + } + if (isPinned || transitionParams.animatePinned) { + float pinnedX = (transitionParams.shouldAnimateTimeX ? this.timeX : timeX) + offsetX; + boolean inAnimation = transitionParams.animatePinned && isPinned; + boolean outAnimation = transitionParams.animatePinned && !isPinned; + if (transitionParams.shouldAnimateTimeX && !inAnimation) { + if (outAnimation) { + pinnedX = transitionParams.animateFromTimeXPinned; + } else { + pinnedX = transitionParams.animateFromTimeXPinned * (1f - transitionParams.animateChangeProgress) + pinnedX * transitionParams.animateChangeProgress; + } + } else { + pinnedX += transitionParams.deltaRight; + } + if (currentMessagesGroup != null && currentMessagesGroup.transitionParams.backgroundChangeBounds) { + pinnedX += currentMessagesGroup.transitionParams.offsetRight; + } + if (transitionParams.animateBackgroundBoundsInner) { + pinnedX += animationOffsetX; + } + + Drawable pinnedDrawable; + if (shouldDrawTimeOnMedia()) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + pinnedDrawable = Theme.chat_msgStickerPinnedDrawable; + } else { + pinnedDrawable = Theme.chat_msgMediaPinnedDrawable; + } + } else { + if (!currentMessageObject.isOutOwner()) { + pinnedDrawable = drawSelectionBackground ? Theme.chat_msgInPinnedSelectedDrawable : Theme.chat_msgInPinnedDrawable; + } else { + pinnedDrawable = drawSelectionBackground ? Theme.chat_msgOutPinnedSelectedDrawable : Theme.chat_msgOutPinnedDrawable; + } + } + if (transitionParams.animatePinned) { + if (isPinned) { + pinnedDrawable.setAlpha((int) (255 * alpha * transitionParams.animateChangeProgress)); + setDrawableBounds(pinnedDrawable, pinnedX, timeY); + } else { + pinnedDrawable.setAlpha((int) (255 * alpha * (1.0f - transitionParams.animateChangeProgress))); + setDrawableBounds(pinnedDrawable, pinnedX, timeY); + } + } else { + pinnedDrawable.setAlpha((int) (255 * alpha)); + setDrawableBounds(pinnedDrawable, pinnedX, timeY); + } + if (useScale) { + canvas.save(); + float cx = pinnedX + pinnedDrawable.getIntrinsicWidth() / 2f; + canvas.scale(scale, scale, cx, pinnedDrawable.getBounds().centerY()); + } + pinnedDrawable.draw(canvas); + pinnedDrawable.setAlpha(255); + + if (isPinned) { + offsetX = pinnedDrawable.getIntrinsicWidth() + AndroidUtilities.dp(6); + } + + if (useScale) { + canvas.restore(); + } + transitionParams.lastTimeXPinned = pinnedX; + } + } + } + + private void drawStatusDrawable(Canvas canvas, boolean drawCheck1, boolean drawCheck2, boolean drawClock, boolean drawError, boolean isBroadcast, float alpha, boolean bigRadius, float timeYOffset, float layoutHeight, float progress, boolean moveCheck, boolean drawSelectionBackground) { + final boolean useScale = progress != 1f && !moveCheck; + float scale = 0.5f + 0.5f * progress; + if (useScale) { + alpha = alpha * progress; + } + float timeY = photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(8.5f); + if (drawClock) { + Drawable drawable; + if (shouldDrawTimeOnMedia()) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + Theme.chat_msgStickerClockDrawable.setAlpha((int) (255 * timeAlpha * alpha)); + setDrawableBounds(Theme.chat_msgStickerClockDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 24 : 22) - Theme.chat_msgStickerClockDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgStickerClockDrawable.getIntrinsicHeight() + timeYOffset); + drawable = Theme.chat_msgStickerClockDrawable; + } else { + setDrawableBounds(Theme.chat_msgMediaClockDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 24 : 22) - Theme.chat_msgMediaClockDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaClockDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgMediaClockDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgMediaClockDrawable; + } + } else { + setDrawableBounds(Theme.chat_msgOutClockDrawable, layoutWidth - AndroidUtilities.dp(18.5f) - Theme.chat_msgOutClockDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.5f) - Theme.chat_msgOutClockDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgOutClockDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgOutClockDrawable; + } + + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + drawable.setAlpha(255); + if (useScale) { + canvas.restore(); + } + invalidate(); + } + if (isBroadcast) { + if (drawCheck1 || drawCheck2) { + Drawable drawable; + if (shouldDrawTimeOnMedia()) { + setDrawableBounds(Theme.chat_msgBroadcastMediaDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 26 : 24) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(14.0f) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgBroadcastMediaDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgBroadcastMediaDrawable; + } else { + setDrawableBounds(Theme.chat_msgBroadcastDrawable, layoutWidth - AndroidUtilities.dp(20.5f) - Theme.chat_msgBroadcastDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - Theme.chat_msgBroadcastDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgBroadcastDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgBroadcastDrawable; + } + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale) { + canvas.restore(); + } + drawable.setAlpha(255); + } + } else { + if (drawCheck2) { + if (shouldDrawTimeOnMedia()) { + Drawable drawable; + if (moveCheck) { + canvas.save(); + } + if (currentMessageObject.shouldDrawWithoutBackground()) { + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); + } + setDrawableBounds(Theme.chat_msgStickerCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgStickerCheckDrawable.getIntrinsicHeight() + timeYOffset); + } else { + setDrawableBounds(Theme.chat_msgStickerCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgStickerCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgStickerCheckDrawable.getIntrinsicHeight() + timeYOffset); + } + Theme.chat_msgStickerCheckDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgStickerCheckDrawable; + } else { + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); + } + setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); + } else { + setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); + } + Theme.chat_msgMediaCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); + drawable = Theme.chat_msgMediaCheckDrawable; + } + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale) { + canvas.restore(); + } + if (moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); + } else { + Drawable drawable; + if (moveCheck) { + canvas.save(); + } + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4) * (1f - progress), 0); + } + drawable = drawSelectionBackground ? Theme.chat_msgOutCheckReadSelectedDrawable : Theme.chat_msgOutCheckReadDrawable; + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + } else { + drawable = drawSelectionBackground ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + } + drawable.setAlpha((int) (255 * alpha)); + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale) { + canvas.restore(); + } + if (moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); + } + } + if (drawCheck1) { + if (shouldDrawTimeOnMedia()) { + Drawable drawable; + if (currentMessageObject.shouldDrawWithoutBackground()) { + setDrawableBounds(Theme.chat_msgStickerHalfCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgStickerHalfCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgStickerHalfCheckDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgStickerHalfCheckDrawable.setAlpha((int) (255 * alpha)); + drawable = Theme.chat_msgStickerHalfCheckDrawable; + } else { + setDrawableBounds(Theme.chat_msgMediaHalfCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaHalfCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaHalfCheckDrawable.getIntrinsicHeight() + timeYOffset); + Theme.chat_msgMediaHalfCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); + drawable = Theme.chat_msgMediaHalfCheckDrawable; + } + if (useScale || moveCheck) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale || moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); + } else { + Drawable drawable = drawSelectionBackground ? Theme.chat_msgOutHalfCheckSelectedDrawable : Theme.chat_msgOutHalfCheckDrawable; + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + drawable.setAlpha((int) (255 * alpha)); + if (useScale || moveCheck) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale || moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); + } + } + } + if (drawError) { + int x; + float y; + if (shouldDrawTimeOnMedia()) { + x = layoutWidth - AndroidUtilities.dp(34.5f); + y = layoutHeight - AndroidUtilities.dp(26.5f) + timeYOffset; + } else { + x = layoutWidth - AndroidUtilities.dp(32); + y = layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 22 : 21) + timeYOffset; + } + rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); + int oldAlpha = Theme.chat_msgErrorPaint.getAlpha(); + Theme.chat_msgErrorPaint.setAlpha((int) (oldAlpha * alpha)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); + Theme.chat_msgErrorPaint.setAlpha(oldAlpha); + setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); + Theme.chat_msgErrorDrawable.setAlpha((int) (255 * alpha)); + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, Theme.chat_msgErrorDrawable.getBounds().centerX(), Theme.chat_msgErrorDrawable.getBounds().centerY()); + } + Theme.chat_msgErrorDrawable.draw(canvas); + Theme.chat_msgErrorDrawable.setAlpha(255); + if (useScale) { + canvas.restore(); } } } @@ -11010,7 +11638,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!currentMessageObject.needDrawBluredPreview()) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); - if (drawPhotoCheckBox) { + if (drawMediaCheckBox) { Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha * (1.0f - checkBoxAnimationProgress))); } else { Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha)); @@ -11193,9 +11821,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { int cy = (int) (photoImage.getImageY2() + AndroidUtilities.dp(30)); - if (!locationExpired) { + if (!locationExpired || transitionParams.animateLocationIsExpired) { forceNotDrawTime = true; - float progress = 1.0f - Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date) / (float) currentMessageObject.messageOwner.media.period; + float progress; + String text; + StaticLayout docTitleLayout = this.docTitleLayout; + StaticLayout infoLayout = this.infoLayout; + float alpha = 1f; + if (transitionParams.animateLocationIsExpired){ + progress = transitionParams.lastDrawLocationExpireProgress; + text = transitionParams.lastDrawLocationExpireText; + docTitleLayout = transitionParams.lastDrawDocTitleLayout; + infoLayout = transitionParams.lastDrawInfoLayout; + alpha = 1f - transitionParams.animateChangeProgress; + } else { + progress = 1.0f - Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date) / (float) currentMessageObject.messageOwner.media.period; + text = LocaleController.formatLocationLeftTime(Math.abs(currentMessageObject.messageOwner.media.period - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date))); + } + rect.set(photoImage.getImageX2() - AndroidUtilities.dp(43), cy - AndroidUtilities.dp(15), photoImage.getImageX2() - AndroidUtilities.dp(13), cy + AndroidUtilities.dp(15)); if (currentMessageObject.isOutOwner()) { Theme.chat_radialProgress2Paint.setColor(Theme.getColor(Theme.key_chat_outInstant)); @@ -11205,22 +11848,49 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_livePaint.setColor(Theme.getColor(Theme.key_chat_inInstant)); } - Theme.chat_radialProgress2Paint.setAlpha(50); + int docTitleAlpha = Theme.chat_locationTitlePaint.getAlpha(); + int infoAlpha = Theme.chat_locationAddressPaint.getAlpha(); + int liveAplha = Theme.chat_livePaint.getAlpha(); + if (alpha != 1f) { + Theme.chat_locationTitlePaint.setAlpha((int) (docTitleAlpha * alpha)); + Theme.chat_locationAddressPaint.setAlpha((int) (infoAlpha * alpha)); + Theme.chat_livePaint.setAlpha((int) (liveAplha * alpha)); + canvas.save(); + canvas.translate(0, -AndroidUtilities.dp(50) * transitionParams.animateChangeProgress); + } + + Theme.chat_radialProgress2Paint.setAlpha((int) (50 * alpha)); canvas.drawCircle(rect.centerX(), rect.centerY(), AndroidUtilities.dp(15), Theme.chat_radialProgress2Paint); - Theme.chat_radialProgress2Paint.setAlpha(255); + Theme.chat_radialProgress2Paint.setAlpha((int) (255 * alpha)); canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); - String text = LocaleController.formatLocationLeftTime(Math.abs(currentMessageObject.messageOwner.media.period - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date))); float w = Theme.chat_livePaint.measureText(text); - canvas.drawText(text, rect.centerX() - w / 2, cy + AndroidUtilities.dp(4), Theme.chat_livePaint); - canvas.save(); - canvas.translate(photoImage.getImageX() + AndroidUtilities.dp(10), photoImage.getImageY2() + AndroidUtilities.dp(10)); - docTitleLayout.draw(canvas); - canvas.translate(0, AndroidUtilities.dp(23)); - infoLayout.draw(canvas); - canvas.restore(); + if (docTitleLayout != null && infoLayout != null) { + canvas.save(); + canvas.translate(photoImage.getImageX() + AndroidUtilities.dp(10), photoImage.getImageY2() + AndroidUtilities.dp(10)); + docTitleLayout.draw(canvas); + canvas.translate(0, AndroidUtilities.dp(23)); + infoLayout.draw(canvas); + canvas.restore(); + } + + if (alpha != 1f) { + Theme.chat_locationTitlePaint.setAlpha(docTitleAlpha); + Theme.chat_locationAddressPaint.setAlpha(infoAlpha); + Theme.chat_livePaint.setAlpha(liveAplha); + canvas.restore(); + } + + transitionParams.lastDrawLocationExpireProgress = progress; + transitionParams.lastDrawLocationExpireText = text; + transitionParams.lastDrawDocTitleLayout = docTitleLayout; + transitionParams.lastDrawInfoLayout = infoLayout; + } else { + transitionParams.lastDrawLocationExpireText = null; + transitionParams.lastDrawDocTitleLayout = null; + transitionParams.lastDrawInfoLayout = null; } int cx = (int) (photoImage.getImageX() + photoImage.getImageWidth() / 2 - AndroidUtilities.dp(31)); @@ -11299,7 +11969,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate otherY = AndroidUtilities.dp(18.5f); } else if (pinnedBottom && pinnedTop) { otherY = AndroidUtilities.dp(18); - } else if (!pinnedBottom && pinnedTop) { + } else if (!pinnedBottom) { otherY = AndroidUtilities.dp(17); } else { otherY = AndroidUtilities.dp(19); @@ -11693,11 +12363,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } videoRadialProgress.draw(canvas); } - if (drawPhotoCheckBox) { - int size = AndroidUtilities.dp(21); - photoCheckBox.setColor(null, null, currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected); - photoCheckBox.setBounds((int) photoImage.getImageX2() - AndroidUtilities.dp(21 + 4), (int) photoImage.getImageY() + AndroidUtilities.dp(4), size, size); - photoCheckBox.draw(canvas); + if (drawMediaCheckBox) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT && !drawPhotoImage) { + int size = AndroidUtilities.dp(20); + mediaCheckBox.setBackgroundType(radialProgress.getMiniIcon() != MediaActionDrawable.ICON_NONE ? 12 : 13); + mediaCheckBox.setBounds(buttonX + AndroidUtilities.dp(28), buttonY + AndroidUtilities.dp(28), size, size); + mediaCheckBox.setColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outTimeText : Theme.key_chat_inTimeText, currentMessageObject.isOutOwner() ? Theme.key_chat_outLoader : Theme.key_chat_inLoader, currentMessageObject.isOutOwner() ? Theme.key_chat_outBubble : Theme.key_chat_inBubble); + mediaCheckBox.setBackgroundDrawable(isDrawSelectionBackground() ? currentBackgroundSelectedDrawable : currentBackgroundDrawable); + } else { + int size = AndroidUtilities.dp(21); + mediaCheckBox.setBackgroundType(0); + mediaCheckBox.setBounds((int) photoImage.getImageX2() - AndroidUtilities.dp(21 + 4), (int) photoImage.getImageY() + AndroidUtilities.dp(4), size, size); + mediaCheckBox.setColor(null, null, currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected); + mediaCheckBox.setBackgroundDrawable(null); + } + mediaCheckBox.draw(canvas); } } @@ -11714,6 +12394,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF ? documentAttach : null; } + public boolean drawPinnedBottom() { + if (currentMessagesGroup != null && currentMessagesGroup.isDocuments) { + if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + return pinnedBottom; + } + return true; + } + return pinnedBottom; + } + + public boolean drawPinnedTop() { + if (currentMessagesGroup != null && currentMessagesGroup.isDocuments) { + if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0) { + return pinnedTop; + } + return true; + } + return pinnedTop; + } + public boolean isPinnedBottom() { return pinnedBottom; } @@ -11881,11 +12581,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public int computeHeight(MessageObject object, MessageObject.GroupedMessages groupedMessages) { - if (object.type == 2 || object.type == 12 || object.type == 9 || + /*if (object.type == 2 || object.type == 12 || object.type == 9 || object.type == 4 || object.type == 14 || object.type == 10 || object.type == 11 || object.type == MessageObject.TYPE_ROUND_VIDEO) { return object.getApproximateHeight(); - } + }*/ photoImage.setIgnoreImageSet(true); avatarImage.setIgnoreImageSet(true); replyImageReceiver.setIgnoreImageSet(true); @@ -12497,28 +13197,58 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return transitionParams; } + public int getTopMediaOffset() { + if (currentMessageObject != null && currentMessageObject.type == 14) { + return mediaOffsetY + namesOffset; + } + return 0; + } + public class TransitionParams { public float lastDrawingImageX, lastDrawingImageY, lastDrawingImageW, lastDrawingImageH; public float lastDrawingCaptionX, lastDrawingCaptionY; + public boolean animateChange; + public int animateFromRepliesTextWidth; + public boolean messageEntering; + public boolean animateLocationIsExpired; + public boolean lastLocatinIsExpired; + public String lastDrawLocationExpireText; + public float lastDrawLocationExpireProgress; + public StaticLayout lastDrawDocTitleLayout; + public StaticLayout lastDrawInfoLayout; + + private boolean lastIsPinned; + private boolean animatePinned; + public float lastTimeXPinned; + public float animateFromTimeXPinned; private int lastRepliesCount; private boolean animateReplies; private StaticLayout lastRepliesLayout; private StaticLayout animateRepliesLayout; + private float animateFromTimeXReplies; + private float lastTimeXReplies; + + private float animateFromTimeXViews; + private float lastTimeXViews; private int lastCommentsCount; private int lastTotalCommentWidth; private int lastCommentArrowX; private int lastCommentUnreadX; private boolean lastCommentDrawUnread; + private float lastCommentX; + private boolean lastDrawCommentNumber; private StaticLayout lastCommentLayout; private boolean animateComments; private StaticLayout animateCommentsLayout; + private float animateCommentX; private int animateTotalCommentWidth; private int animateCommentArrowX; private int animateCommentUnreadX; private boolean animateCommentDrawUnread; + private boolean animateDrawCommentNumber; private boolean animateSign; private float animateNameX; @@ -12554,11 +13284,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean animateEditedEnter; private StaticLayout animateEditedLayout; private StaticLayout animateTimeLayout; + private int animateTimeWidth; + private int lastTimeWidth; private boolean lastDrawingEdited; boolean animateReplaceCaptionLayout; private StaticLayout animateOutCaptionLayout; private StaticLayout lastDrawingCaptionLayout; + public boolean lastDrawTime; + public int lastTimeX; + public int animateFromTimeX; + public boolean shouldAnimateTimeX; public boolean animateDrawingTimeAlpha; @@ -12572,6 +13308,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private float animateFromButtonY; private boolean animateButton; + public int lastStatusDrawableParams = -1; + + private int lastViewsCount; + private StaticLayout lastViewsLayout; + private StaticLayout animateViewsLayout; + + private boolean lastShouldDrawTimeOnMedia; + private boolean animateShouldDrawTimeOnMedia; + private boolean lastShouldDrawMenuDrawable; + private boolean animateShouldDrawMenuDrawable; + private StaticLayout lastTimeLayout; + + public int lastTopOffset; + public void recordDrawingState() { wasDraw = true; lastDrawingImageX = photoImage.getImageX(); @@ -12602,16 +13352,32 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastCommentArrowX = commentArrowX; lastCommentUnreadX = commentUnreadX; lastCommentDrawUnread = commentDrawUnread; + lastCommentX = commentX; + lastDrawCommentNumber = drawCommentNumber; } - if (repliesLayout != null) { - lastRepliesCount = getRepliesCount(); - lastRepliesLayout = repliesLayout; - } + + lastRepliesCount = getRepliesCount(); + this.lastViewsCount = getMessageObject().messageOwner.views; + lastRepliesLayout = repliesLayout; + lastViewsLayout = viewsLayout; + + lastIsPinned = isPinned; lastSignMessage = lastPostAuthor; lastButtonX = buttonX; lastButtonY = buttonY; + + lastDrawTime = !forceNotDrawTime; + lastTimeX = timeX; + lastTimeLayout = timeLayout; + lastTimeWidth = timeWidth; + + lastShouldDrawTimeOnMedia = shouldDrawTimeOnMedia(); + lastTopOffset = getTopMediaOffset(); + lastShouldDrawMenuDrawable = shouldDrawMenuDrawable(); + + lastLocatinIsExpired = locationExpired; } public boolean animateChange() { @@ -12631,13 +13397,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate String text = timeLayout.getText().toString(); int i = text.indexOf(editedStr); if (i >= 0) { - animateEditedLayout = new StaticLayout(editedStr, Theme.chat_timePaint, timeTextWidth + AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); - spannableStringBuilder.append(editedStr); - spannableStringBuilder.append(text.substring(editedStr.length())); - spannableStringBuilder.setSpan(new EmptyStubSpan(), 0, editedStr.length(), 0); - animateTimeLayout = new StaticLayout(spannableStringBuilder, Theme.chat_timePaint, timeTextWidth + AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (i == 0) { + animateEditedLayout = new StaticLayout(editedStr, Theme.chat_timePaint, timeTextWidth + AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append(editedStr); + spannableStringBuilder.append(text.substring(editedStr.length())); + spannableStringBuilder.setSpan(new EmptyStubSpan(), 0, editedStr.length(), 0); + animateTimeLayout = new StaticLayout(spannableStringBuilder, Theme.chat_timePaint, timeTextWidth + AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } else { + animateEditedLayout = null; + animateTimeLayout = lastTimeLayout; + } animateEditedEnter = true; + animateTimeWidth = lastTimeWidth; + animateFromTimeX = lastTimeX; changed = true; } } @@ -12645,8 +13418,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (captionLayout != lastDrawingCaptionLayout) { String oldCaption = lastDrawingCaptionLayout == null ? null : lastDrawingCaptionLayout.getText().toString(); String currentCaption = captionLayout == null ? null : captionLayout.getText().toString(); - if (currentCaption != null && ((oldCaption == null && currentCaption != null) || - !oldCaption.equals(currentCaption))) { + if (currentCaption != null && (oldCaption == null || !oldCaption.equals(currentCaption))) { animateReplaceCaptionLayout = true; animateOutCaptionLayout = lastDrawingCaptionLayout; changed = true; @@ -12664,7 +13436,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate transitionBotButtons.addAll(lastDrawBotButtons); } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (buttonX != lastButtonX || buttonY != lastButtonY) { animateFromButtonX = lastButtonX; animateFromButtonY = lastButtonY; @@ -12673,18 +13445,39 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (repliesLayout != null && lastRepliesCount != getRepliesCount()) { + boolean timeDrawablesIsChanged = false; + + if (lastIsPinned != isPinned) { + animatePinned = true; + changed = true; + timeDrawablesIsChanged = true; + } + + if ((lastRepliesLayout != null || repliesLayout != null) && lastRepliesCount != getRepliesCount()) { animateRepliesLayout = lastRepliesLayout; animateReplies = true; changed = true; + timeDrawablesIsChanged = true; + } + + if (lastViewsLayout != null && this.lastViewsCount != getMessageObject().messageOwner.views) { + animateViewsLayout = lastViewsLayout; + changed = true; + timeDrawablesIsChanged = true; } if (commentLayout != null && lastCommentsCount != getRepliesCount()) { - animateCommentsLayout = lastCommentLayout; + if (lastCommentLayout != null && !TextUtils.equals(lastCommentLayout.getText(), commentLayout.getText())) { + animateCommentsLayout = lastCommentLayout; + } else { + animateCommentsLayout = null; + } animateTotalCommentWidth = lastTotalCommentWidth; + animateCommentX = lastCommentX; animateCommentArrowX = lastCommentArrowX; animateCommentUnreadX = lastCommentUnreadX; animateCommentDrawUnread = lastCommentDrawUnread; + animateDrawCommentNumber = lastDrawCommentNumber; animateComments = true; changed = true; } @@ -12695,15 +13488,43 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate changed = true; } + if (lastDrawTime == forceNotDrawTime) { + animateDrawingTimeAlpha = true; + animateViewsLayout = null; + changed = true; + } else if (lastShouldDrawTimeOnMedia != shouldDrawTimeOnMedia()) { + animateEditedEnter = false; + animateShouldDrawTimeOnMedia = true; + animateFromTimeX = lastTimeX; + animateTimeLayout = lastTimeLayout; + animateTimeWidth = lastTimeWidth; + changed = true; + } else if (timeDrawablesIsChanged || timeX != lastTimeX) { + shouldAnimateTimeX = true; + animateTimeWidth = lastTimeWidth; + animateFromTimeX = lastTimeX; + animateFromTimeXViews = lastTimeXViews; + animateFromTimeXReplies = lastTimeXReplies; + animateFromTimeXPinned = lastTimeXPinned; + } + + if (lastShouldDrawMenuDrawable != shouldDrawMenuDrawable()) { + animateShouldDrawMenuDrawable = true; + } + + if (lastLocatinIsExpired != locationExpired) { + animateLocationIsExpired = true; + } return changed; } public void onDetach() { wasDraw = false; - // resetAnimation(); } public void resetAnimation() { + animateChange = false; + animatePinned = false; animateBackgroundBoundsInner = false; deltaLeft = 0; deltaRight = 0; @@ -12742,12 +13563,52 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animateComments = false; animateCommentsLayout = null; - + animateViewsLayout = null; + animateShouldDrawTimeOnMedia = false; + animateShouldDrawMenuDrawable = false; + shouldAnimateTimeX = false; animateSign = false; + animateDrawingTimeAlpha = false; + animateLocationIsExpired = false; } public boolean supportChangeAnimation() { return true; } + + public int createStatusDrawableParams() { + if (currentMessageObject.isOutOwner()) { + boolean drawCheck1 = false; + boolean drawCheck2 = false; + boolean drawClock = false; + boolean drawError = false; + boolean isBroadcast = (int) (currentMessageObject.getDialogId() >> 32) == 1; + + if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { + drawCheck2 = false; + drawClock = true; + drawError = false; + } else if (currentMessageObject.isSendError()) { + drawCheck2 = false; + drawClock = false; + drawError = true; + } else if (currentMessageObject.isSent()) { + if (!currentMessageObject.scheduled && !currentMessageObject.isUnread()) { + drawCheck1 = true; + } else { + drawCheck1 = false; + } + drawCheck2 = true; + drawClock = false; + drawError = false; + } + return (drawCheck1 ? 1 : 0) | (drawCheck2 ? 2 : 0) | (drawClock ? 4 : 0) | (drawError ? 8 : 0) | (isBroadcast ? 16 : 0); + } else { + boolean drawClock = currentMessageObject.isSending() || currentMessageObject.isEditing(); + boolean drawError = currentMessageObject.isSendError(); + + return (drawClock ? 4 : 0) | (drawError ? 8 : 0); + } + } } } 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 f79e7f929..4bd26912b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -8,6 +8,9 @@ package org.telegram.ui.Cells; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; @@ -23,7 +26,6 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; -import android.text.style.ForegroundColorSpan; import android.text.style.ReplacementSpan; import android.view.HapticFeedbackConstants; import android.view.accessibility.AccessibilityEvent; @@ -52,13 +54,17 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.ImageReceiver; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.EmptyStubSpan; +import org.telegram.ui.Components.ForegroundColorSpanThemable; import org.telegram.ui.Components.PullForegroundDrawable; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.StatusDrawable; import org.telegram.ui.Components.TypefaceSpan; +import org.telegram.ui.Components.TypingDotsDrawable; import org.telegram.ui.DialogsActivity; import java.util.ArrayList; @@ -162,6 +168,7 @@ public class DialogCell extends BaseCell { private TLRPC.Chat chat; private TLRPC.EncryptedChat encryptedChat; private CharSequence lastPrintString; + private int printingStringType; private TLRPC.DraftMessage draftMessage; private CheckBox2 checkBox; @@ -193,6 +200,8 @@ public class DialogCell extends BaseCell { private boolean drawCheck2; private boolean drawClock; private int checkDrawLeft; + private int checkDrawLeft1; + private int clockDrawLeft; private int checkDrawTop; private int halfCheckDrawLeft; @@ -236,6 +245,13 @@ public class DialogCell extends BaseCell { private RectF rect = new RectF(); + private int animateToStatusDrawableParams; + private int animateFromStatusDrawableParams; + private int lastStatusDrawableParams = -1; + private float statusDrawableProgress; + private boolean statusDrawableAnimationInProgress; + private ValueAnimator statusDrawableAnimator; + public static class BounceInterpolator implements Interpolator { public float getInterpolation(float t) { @@ -276,6 +292,14 @@ public class DialogCell extends BaseCell { } public void setDialog(TLRPC.Dialog dialog, int type, int folder) { + if (currentDialogId != dialog.id) { + if (statusDrawableAnimator != null) { + statusDrawableAnimator.removeAllListeners(); + statusDrawableAnimator.cancel(); + } + statusDrawableAnimationInProgress = false; + lastStatusDrawableParams = -1; + } currentDialogId = dialog.id; isDialogCell = true; if (dialog instanceof TLRPC.TL_dialogFolder) { @@ -311,6 +335,9 @@ public class DialogCell extends BaseCell { } public void setDialog(long dialog_id, MessageObject messageObject, int date, boolean useMe) { + if (currentDialogId != dialog_id) { + lastStatusDrawableParams = -1; + } currentDialogId = dialog_id; message = messageObject; useMeForMyMessages = useMe; @@ -462,6 +489,7 @@ public class DialogCell extends BaseCell { return Emoji.replaceEmoji(builder, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(17), false); } + public void buildLayout() { int thumbSize; if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { @@ -493,7 +521,7 @@ public class DialogCell extends BaseCell { CharSequence messageNameString = null; CharSequence printingString = null; if (isDialogCell) { - printingString = MessagesController.getInstance(currentAccount).getPrintingString(currentDialogId, 0); + printingString = MessagesController.getInstance(currentAccount).getPrintingString(currentDialogId, 0, true); } TextPaint currentMessagePaint = Theme.dialogs_messagePaint[paintIndex]; boolean checkMessage = true; @@ -509,6 +537,7 @@ public class DialogCell extends BaseCell { int offsetName = 0; boolean showChecks = !UserObject.isUserSelf(user) && !useMeForMyMessages; boolean drawTime = true; + printingStringType = -1; String messageFormat; boolean hasNameInMessage; @@ -601,7 +630,7 @@ public class DialogCell extends BaseCell { if (customDialog.isMedia) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, message.messageText)); - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_attachMessage), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { String mess = customDialog.message; if (mess.length() > 150) { @@ -772,8 +801,18 @@ public class DialogCell extends BaseCell { } if (printingString != null) { - lastPrintString = messageString = printingString; + lastPrintString = printingString; + printingStringType = MessagesController.getInstance(currentAccount).getPrintingStringType(currentDialogId, 0); + StatusDrawable statusDrawable = Theme.getChatStatusDrawable(printingStringType); + int startPadding = 0; + if (statusDrawable != null) { + startPadding = statusDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3); + } + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append(" ").append(TextUtils.replace(printingString, new String[]{"..."}, new String[]{""})).setSpan(new FixedWidthSpan(startPadding), 0, 1, 0); + messageString = spannableStringBuilder; currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; + checkMessage = false; } else { lastPrintString = null; if (draftMessage != null) { @@ -784,7 +823,7 @@ public class DialogCell extends BaseCell { messageString = ""; } else { SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(messageNameString); - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, messageNameString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_draft), 0, messageNameString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); messageString = stringBuilder; } } else { @@ -794,7 +833,7 @@ public class DialogCell extends BaseCell { } SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); if (!useForceThreeLines && !SharedConfig.useThreeLinesLayout) { - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_draft), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } messageString = Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(20), false); } @@ -819,7 +858,13 @@ public class DialogCell extends BaseCell { } } } else { - messageString = ""; + if (dialogsType == 3 && UserObject.isUserSelf(user)) { + messageString = LocaleController.getString("SavedMessagesInfo", R.string.SavedMessagesInfo); + showChecks = false; + drawTime = false; + } else { + messageString = ""; + } } } else { TLRPC.User fromUser = null; @@ -875,7 +920,7 @@ public class DialogCell extends BaseCell { } } } - if (chat != null && chat.id > 0 && fromChat == null) { + if (chat != null && chat.id > 0 && fromChat == null && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat))) { if (message.isOutOwner()) { messageNameString = LocaleController.getString("FromYou", R.string.FromYou); } else if (fromUser != null) { @@ -943,14 +988,16 @@ public class DialogCell extends BaseCell { innerMessage = innerMessage.replace('\n', ' '); stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, innerMessage, messageNameString)); try { - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), hasNameInMessage ? messageNameString.length() + 2 : 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_attachMessage), hasNameInMessage ? messageNameString.length() + 2 : 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (Exception e) { FileLog.e(e); } } else if (message.messageOwner.message != null) { String mess = message.messageOwner.message; if (message.hasHighlightedWords()) { - mess = mess.replace('\n', ' ').replaceAll(" +", " ").trim(); + if (message.messageTrimmedToHighlight != null) { + mess = message.messageTrimmedToHighlight; + } int w = getMeasuredWidth() - AndroidUtilities.dp(72 + 23 + 10); if (hasNameInMessage) { if (!TextUtils.isEmpty(messageNameString)) { @@ -959,7 +1006,7 @@ public class DialogCell extends BaseCell { w -= currentMessagePaint.measureText(": "); } if (w > 0) { - mess = AndroidUtilities.ellipsizeCenterEnd(mess, message.highlightedWords.get(0), w, currentMessagePaint).toString(); + mess = AndroidUtilities.ellipsizeCenterEnd(mess, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); } } else { if (mess.length() > 150) { @@ -974,7 +1021,7 @@ public class DialogCell extends BaseCell { int thumbInsertIndex = 0; if (!useForceThreeLines && !SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0 && stringBuilder.length() > 0) { try { - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_nameMessage)), 0, thumbInsertIndex = messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_nameMessage), 0, thumbInsertIndex = messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); offsetName = thumbInsertIndex; } catch (Exception e) { FileLog.e(e); @@ -1017,7 +1064,10 @@ public class DialogCell extends BaseCell { emoji = "\uD83D\uDCCE "; } if (message.hasHighlightedWords() && !TextUtils.isEmpty(message.messageOwner.message)) { - String str = message.messageOwner.message.replace('\n', ' ').replaceAll(" +", " ").trim(); + String str = message.messageTrimmedToHighlight; + if (message.messageTrimmedToHighlight != null) { + str = message.messageTrimmedToHighlight; + } int w = getMeasuredWidth() - AndroidUtilities.dp(72 + 23 + 24); if (hasNameInMessage) { if (!TextUtils.isEmpty(messageNameString)) { @@ -1026,7 +1076,7 @@ public class DialogCell extends BaseCell { w -= currentMessagePaint.measureText(": "); } if (w > 0) { - str = AndroidUtilities.ellipsizeCenterEnd(str, message.highlightedWords.get(0), w, currentMessagePaint).toString(); + str = AndroidUtilities.ellipsizeCenterEnd(str, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); } messageString = emoji + str; } else { @@ -1042,9 +1092,12 @@ public class DialogCell extends BaseCell { messageString = String.format("\uD83C\uDFA7 %s - %s", message.getMusicAuthor(), message.getMusicTitle()); } else { if (message.hasHighlightedWords() && !TextUtils.isEmpty(message.messageOwner.message)){ - messageString = message.messageOwner.message.replace('\n', ' ').trim(); + messageString = message.messageTrimmedToHighlight; + if (message.messageTrimmedToHighlight != null) { + messageString = message.messageTrimmedToHighlight; + } int w = getMeasuredWidth() - AndroidUtilities.dp(72 + 23 ); - messageString = AndroidUtilities.ellipsizeCenterEnd(messageString, message.highlightedWords.get(0), w, currentMessagePaint).toString(); + messageString = AndroidUtilities.ellipsizeCenterEnd(messageString, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); } else { messageString = message.messageText; } @@ -1056,9 +1109,12 @@ public class DialogCell extends BaseCell { } if (hasMessageThumb) { if (message.hasHighlightedWords() && !TextUtils.isEmpty(message.messageOwner.message)) { - messageString = message.messageOwner.message.replace('\n', ' ').replaceAll(" +", " ").trim(); + messageString = message.messageTrimmedToHighlight; + if (message.messageTrimmedToHighlight != null) { + messageString = message.messageTrimmedToHighlight; + } int w = getMeasuredWidth() - AndroidUtilities.dp(72 + 23 + thumbSize + 6); - messageString = AndroidUtilities.ellipsizeCenterEnd(messageString, message.highlightedWords.get(0), w, currentMessagePaint).toString(); + messageString = AndroidUtilities.ellipsizeCenterEnd(messageString, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); } else { if (messageString.length() > 150) { messageString = messageString.subSequence(0, 150); @@ -1250,9 +1306,9 @@ public class DialogCell extends BaseCell { int w = Theme.dialogs_clockDrawable.getIntrinsicWidth() + AndroidUtilities.dp(5); nameWidth -= w; if (!LocaleController.isRTL) { - checkDrawLeft = timeLeft - w; + clockDrawLeft = timeLeft - w; } else { - checkDrawLeft = timeLeft + timeWidth + AndroidUtilities.dp(5); + clockDrawLeft = timeLeft + timeWidth + AndroidUtilities.dp(5); nameLeft += w; } } else if (drawCheck2) { @@ -1270,9 +1326,9 @@ public class DialogCell extends BaseCell { } } else { if (!LocaleController.isRTL) { - checkDrawLeft = timeLeft - w; + checkDrawLeft1 = timeLeft - w; } else { - checkDrawLeft = timeLeft + timeWidth + AndroidUtilities.dp(5); + checkDrawLeft1 = timeLeft + timeWidth + AndroidUtilities.dp(5); nameLeft += w; } } @@ -1592,6 +1648,71 @@ public class DialogCell extends BaseCell { } } + private void drawCheckStatus(Canvas canvas, boolean drawClock, boolean drawCheck1, boolean drawCheck2, boolean moveCheck, float alpha) { + float scale = 0.5f + 0.5f * alpha; + if (drawClock) { + setDrawableBounds(Theme.dialogs_clockDrawable, clockDrawLeft, checkDrawTop); + if (alpha != 1f) { + canvas.save(); + canvas.scale(scale, scale, Theme.dialogs_clockDrawable.getBounds().centerX(), Theme.dialogs_halfCheckDrawable.getBounds().centerY()); + Theme.dialogs_clockDrawable.setAlpha((int) (255 * alpha)); + } + Theme.dialogs_clockDrawable.draw(canvas); + if (alpha != 1f) { + canvas.restore(); + Theme.dialogs_clockDrawable.setAlpha(255); + } + invalidate(); + } else if (drawCheck2) { + if (drawCheck1) { + setDrawableBounds(Theme.dialogs_halfCheckDrawable, halfCheckDrawLeft, checkDrawTop); + if (moveCheck) { + canvas.save(); + canvas.scale(scale, scale, Theme.dialogs_halfCheckDrawable.getBounds().centerX(), Theme.dialogs_halfCheckDrawable.getBounds().centerY()); + Theme.dialogs_halfCheckDrawable.setAlpha((int) (255 * alpha)); + } + if (!moveCheck && alpha != 0) { + canvas.save(); + canvas.scale(scale, scale, Theme.dialogs_halfCheckDrawable.getBounds().centerX(), Theme.dialogs_halfCheckDrawable.getBounds().centerY()); + Theme.dialogs_halfCheckDrawable.setAlpha((int) (255 * alpha)); + Theme.dialogs_checkReadDrawable.setAlpha((int) (255 * alpha)); + } + + Theme.dialogs_halfCheckDrawable.draw(canvas); + + if (moveCheck) { + canvas.restore(); + canvas.save(); + canvas.translate(AndroidUtilities.dp(4) * (1f - alpha), 0); + } + setDrawableBounds(Theme.dialogs_checkReadDrawable, checkDrawLeft, checkDrawTop); + Theme.dialogs_checkReadDrawable.draw(canvas); + if (moveCheck) { + canvas.restore(); + Theme.dialogs_halfCheckDrawable.setAlpha(255); + } + + if (!moveCheck && alpha != 0) { + canvas.restore(); + Theme.dialogs_halfCheckDrawable.setAlpha(255); + Theme.dialogs_checkReadDrawable.setAlpha(255); + } + } else { + setDrawableBounds(Theme.dialogs_checkDrawable, checkDrawLeft1, checkDrawTop); + if (alpha != 1f) { + canvas.save(); + canvas.scale(scale, scale, Theme.dialogs_checkDrawable.getBounds().centerX(), Theme.dialogs_halfCheckDrawable.getBounds().centerY()); + Theme.dialogs_checkDrawable.setAlpha((int) (255 * alpha)); + } + Theme.dialogs_checkDrawable.draw(canvas); + if (alpha != 1f) { + canvas.restore(); + Theme.dialogs_checkDrawable.setAlpha(255); + } + } + } + } + public boolean isPointInsideAvatar(float x, float y) { if (!LocaleController.isRTL) { return x >= 0 && x < AndroidUtilities.dp(60); @@ -1749,7 +1870,7 @@ public class DialogCell extends BaseCell { } if (isDialogCell) { if ((mask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) { - CharSequence printString = MessagesController.getInstance(currentAccount).getPrintingString(currentDialogId, 0); + CharSequence printString = MessagesController.getInstance(currentAccount).getPrintingString(currentDialogId, 0, true); if (lastPrintString != null && printString == null || lastPrintString == null && printString != null || lastPrintString != null && printString != null && !lastPrintString.equals(printString)) { continueUpdate = true; } @@ -2186,25 +2307,54 @@ public class DialogCell extends BaseCell { FileLog.e(e); } canvas.restore(); - } - if (currentDialogFolderId == 0) { - if (drawClock) { - setDrawableBounds(Theme.dialogs_clockDrawable, checkDrawLeft, checkDrawTop); - Theme.dialogs_clockDrawable.draw(canvas); - } else if (drawCheck2) { - if (drawCheck1) { - setDrawableBounds(Theme.dialogs_halfCheckDrawable, halfCheckDrawLeft, checkDrawTop); - Theme.dialogs_halfCheckDrawable.draw(canvas); - setDrawableBounds(Theme.dialogs_checkReadDrawable, checkDrawLeft, checkDrawTop); - Theme.dialogs_checkReadDrawable.draw(canvas); - } else { - setDrawableBounds(Theme.dialogs_checkDrawable, checkDrawLeft, checkDrawTop); - Theme.dialogs_checkDrawable.draw(canvas); + if (printingStringType >= 0) { + StatusDrawable statusDrawable = Theme.getChatStatusDrawable(printingStringType); + if (statusDrawable != null) { + canvas.save(); + int left = LocaleController.isRTL ? messageLeft + messageLayout.getWidth() - statusDrawable.getIntrinsicWidth() : messageLeft; + if (printingStringType == 1 || printingStringType == 4) { + canvas.translate(left, messageTop + (printingStringType == 1 ? AndroidUtilities.dp(1) : 0)); + } else { + canvas.translate(left, messageTop + (AndroidUtilities.dp(18) - statusDrawable.getIntrinsicHeight()) / 2f); + } + statusDrawable.draw(canvas); + invalidate(left, messageTop, left + statusDrawable.getIntrinsicWidth(), messageTop + statusDrawable.getIntrinsicHeight()); + canvas.restore(); } } } + + if (currentDialogFolderId == 0) { + int currentStatus = (drawClock ? 1 : 0) + (drawCheck1 ? 2 : 0) + (drawCheck2 ? 4 : 0); + if (lastStatusDrawableParams >= 0 && lastStatusDrawableParams != currentStatus && !statusDrawableAnimationInProgress) { + createStatusDrawableAnimator(lastStatusDrawableParams, currentStatus); + } + if (statusDrawableAnimationInProgress) { + currentStatus = animateToStatusDrawableParams; + } + + boolean drawClock = (currentStatus & 1) != 0; + boolean drawCheck1 = (currentStatus & 2) != 0; + boolean drawCheck2 = (currentStatus & 4) != 0; + + if (statusDrawableAnimationInProgress) { + boolean outDrawClock = (animateFromStatusDrawableParams & 1) != 0; + boolean outDrawCheck1 = (animateFromStatusDrawableParams & 2) != 0; + boolean outDrawCheck2 = (animateFromStatusDrawableParams & 4) != 0; + if (!drawClock && !outDrawClock && outDrawCheck2 && !outDrawCheck1 && drawCheck1 && drawCheck2) { + drawCheckStatus(canvas, drawClock, drawCheck1, drawCheck2, true, statusDrawableProgress); + } else { + drawCheckStatus(canvas, outDrawClock, outDrawCheck1, outDrawCheck2, false, 1f - statusDrawableProgress); + drawCheckStatus(canvas, drawClock, drawCheck1, drawCheck2, false, statusDrawableProgress); + } + } else { + drawCheckStatus(canvas, drawClock, drawCheck1, drawCheck2, false,1f); + } + lastStatusDrawableParams = (this.drawClock ? 1 : 0) + (this.drawCheck1 ? 2 : 0) + (this.drawCheck2 ? 4 : 0); + } + if (dialogMuted && !drawVerified && !drawScam) { setDrawableBounds(Theme.dialogs_muteDrawable, nameMuteLeft - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 0 : 1), AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 13.5f : 17.5f)); Theme.dialogs_muteDrawable.draw(canvas); @@ -2447,6 +2597,35 @@ public class DialogCell extends BaseCell { } } + private void createStatusDrawableAnimator(int lastStatusDrawableParams, int currentStatus) { + statusDrawableProgress = 0f; + statusDrawableAnimator = ValueAnimator.ofFloat(0,1f); + statusDrawableAnimator.setDuration(220); + + statusDrawableAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animateFromStatusDrawableParams = lastStatusDrawableParams; + animateToStatusDrawableParams = currentStatus; + statusDrawableAnimator.addUpdateListener(valueAnimator -> { + statusDrawableProgress = (float) valueAnimator.getAnimatedValue(); + invalidate(); + }); + statusDrawableAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + int currentStatus = (DialogCell.this.drawClock ? 1 : 0) + (DialogCell.this.drawCheck1 ? 2 : 0) + (DialogCell.this.drawCheck2 ? 4 : 0); + if (animateToStatusDrawableParams != currentStatus) { + createStatusDrawableAnimator(animateToStatusDrawableParams, currentStatus); + } else { + statusDrawableAnimationInProgress = false; + DialogCell.this.lastStatusDrawableParams = animateToStatusDrawableParams; + } + invalidate(); + } + }); + statusDrawableAnimationInProgress = true; + statusDrawableAnimator.start(); + } + public void startOutAnimation() { if (archivedChatsDrawable != null) { archivedChatsDrawable.outCy = avatarImage.getCenterY(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index 494a660b2..6b1becbaf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -146,7 +146,7 @@ public class DrawerProfileCell extends FrameLayout { } Theme.ThemeInfo themeInfo = Theme.getActiveTheme(); if (dayThemeName.equals(nightThemeName)) { - if (themeInfo.isDark()) { + if (themeInfo.isDark() || dayThemeName.equals("Dark Blue") || dayThemeName.equals("Night")) { dayThemeName = "Blue"; } else { nightThemeName = "Dark Blue"; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index 1ff9d296a..0152ee1a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -90,6 +90,29 @@ public class MentionCell extends LinearLayout { usernameTextView.setVisibility(VISIBLE); } + public void setChat(TLRPC.Chat chat) { + if (chat == null) { + nameTextView.setText(""); + usernameTextView.setText(""); + imageView.setImageDrawable(null); + return; + } + avatarDrawable.setInfo(chat); + if (chat.photo != null && chat.photo.photo_small != null) { + imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); + } else { + imageView.setImageDrawable(avatarDrawable); + } + nameTextView.setText(chat.title); + if (chat.username != null) { + usernameTextView.setText("@" + chat.username); + } else { + usernameTextView.setText(""); + } + imageView.setVisibility(VISIBLE); + usernameTextView.setVisibility(VISIBLE); + } + public void setText(String text) { imageView.setVisibility(INVISIBLE); usernameTextView.setVisibility(INVISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java index 1e65515e6..329da7e7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -100,6 +100,7 @@ public class SendLocationCell extends FrameLayout { accurateTextView.setAlpha(value ? 1.0f : 0.5f); imageView.setAlpha(value ? 1.0f : 0.5f); } + checkText(); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java index ff4d541e8..df5757a3e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java @@ -175,7 +175,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F CharSequence caption = Emoji.replaceEmoji(currentMessageObject.messageOwner.message.replace("\n", " ").replaceAll(" +", " ").trim(), Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); CharSequence sequence = AndroidUtilities.highlightText(caption, currentMessageObject.highlightedWords); if (sequence != null) { - sequence = TextUtils.ellipsize(AndroidUtilities.ellipsizeCenterEnd(sequence, currentMessageObject.highlightedWords.get(0), maxWidth, captionTextPaint), captionTextPaint, maxWidth, TextUtils.TruncateAt.END); + sequence = TextUtils.ellipsize(AndroidUtilities.ellipsizeCenterEnd(sequence, currentMessageObject.highlightedWords.get(0), maxWidth, captionTextPaint, 130), captionTextPaint, maxWidth, TextUtils.TruncateAt.END); captionLayout = new StaticLayout(sequence, captionTextPaint, maxWidth + AndroidUtilities.dp(4), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index 47298c1c4..f0fd23955 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -530,7 +530,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle int h = AndroidUtilities.dp(5 + 29) + nameTextView.getMeasuredHeight() + (needDivider ? 1 : 0); if (caption != null && captionTextView != null && message.hasHighlightedWords()) { ignoreRequestLayout = true; - captionTextView.setText(AndroidUtilities.ellipsizeCenterEnd(caption, message.highlightedWords.get(0), captionTextView.getMeasuredWidth(), captionTextView.getPaint())); + captionTextView.setText(AndroidUtilities.ellipsizeCenterEnd(caption, message.highlightedWords.get(0), captionTextView.getMeasuredWidth(), captionTextView.getPaint(), 130)); ignoreRequestLayout = false; h += captionTextView.getMeasuredHeight() + AndroidUtilities.dp(3); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 19084291a..f29096a6d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -352,7 +352,7 @@ public class SharedLinkCell extends FrameLayout { CharSequence caption = Emoji.replaceEmoji(message.messageOwner.message.replace("\n", " ").replaceAll(" +", " ").trim(), Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); CharSequence sequence = AndroidUtilities.highlightText(caption, message.highlightedWords); if (sequence != null) { - sequence = TextUtils.ellipsize(AndroidUtilities.ellipsizeCenterEnd(sequence, message.highlightedWords.get(0), maxWidth, captionTextPaint), captionTextPaint, maxWidth, TextUtils.TruncateAt.END); + sequence = TextUtils.ellipsize(AndroidUtilities.ellipsizeCenterEnd(sequence, message.highlightedWords.get(0), maxWidth, captionTextPaint, 130), captionTextPaint, maxWidth, TextUtils.TruncateAt.END); captionLayout = new StaticLayout(sequence, captionTextPaint, maxWidth + AndroidUtilities.dp(4), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java index bab718860..070f40012 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -1491,7 +1491,7 @@ public abstract class TextSelectionHelper 0) { + } else if (messageObject != null && messageObject.textLayoutBlocks != null && messageObject.textLayoutBlocks.size() > 0) { MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(messageObject.textLayoutBlocks.size() - 1); textArea.set( maybeTextX, maybeTextY, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java index 5bb79fd82..35750699c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java @@ -211,7 +211,7 @@ public class ChangeBioActivity extends BaseFragment { FileLog.e(e); } userFull.about = newName; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.userInfoDidLoad, user.id, userFull, null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.userInfoDidLoad, user.id, userFull); finishFragment(); }); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 19f1157ba..289623915 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -2475,13 +2475,13 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInClockDrawable}, null, Theme.key_chat_inSentClock)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInSelectedClockDrawable}, null, Theme.key_chat_inSentClockSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgStickerHalfCheckDrawable, Theme.chat_msgStickerCheckDrawable, Theme.chat_msgStickerClockDrawable, Theme.chat_msgStickerViewsDrawable, Theme.chat_msgStickerRepliesDrawable}, null, Theme.key_chat_serviceText)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgStickerHalfCheckDrawable, Theme.chat_msgStickerCheckDrawable, Theme.chat_msgStickerClockDrawable, Theme.chat_msgStickerViewsDrawable, Theme.chat_msgStickerRepliesDrawable, Theme.chat_msgStickerPinnedDrawable}, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaClockDrawable}, null, Theme.key_chat_mediaSentClock)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsDrawable, Theme.chat_msgOutRepliesDrawable}, null, Theme.key_chat_outViews)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsSelectedDrawable, Theme.chat_msgOutRepliesSelectedDrawable}, null, Theme.key_chat_outViewsSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsDrawable, Theme.chat_msgInRepliesDrawable}, null, Theme.key_chat_inViews)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsSelectedDrawable, Theme.chat_msgInRepliesSelectedDrawable}, null, Theme.key_chat_inViewsSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaViewsDrawable, Theme.chat_msgMediaRepliesDrawable}, null, Theme.key_chat_mediaViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsDrawable, Theme.chat_msgOutRepliesDrawable, Theme.chat_msgOutPinnedDrawable}, null, Theme.key_chat_outViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsSelectedDrawable, Theme.chat_msgOutRepliesSelectedDrawable, Theme.chat_msgOutPinnedSelectedDrawable}, null, Theme.key_chat_outViewsSelected)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsDrawable, Theme.chat_msgInRepliesDrawable, Theme.chat_msgInPinnedDrawable}, null, Theme.key_chat_inViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsSelectedDrawable, Theme.chat_msgInRepliesSelectedDrawable, Theme.chat_msgInPinnedSelectedDrawable}, null, Theme.key_chat_inViewsSelected)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaViewsDrawable, Theme.chat_msgMediaRepliesDrawable, Theme.chat_msgMediaPinnedDrawable}, null, Theme.key_chat_mediaViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutMenuDrawable}, null, Theme.key_chat_outMenu)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutMenuSelectedDrawable}, null, Theme.key_chat_outMenuSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInMenuDrawable}, null, Theme.key_chat_inMenu)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Charts/BaseChartView.java b/TMessagesProj/src/main/java/org/telegram/ui/Charts/BaseChartView.java index 203a16705..2b718acc1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Charts/BaseChartView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Charts/BaseChartView.java @@ -17,6 +17,7 @@ import android.graphics.RectF; import android.os.Build; import android.os.Bundle; import android.text.TextPaint; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -1465,6 +1466,7 @@ public abstract class BaseChartView legendSignatureView.setVisibility(VISIBLE); selectionA = 1f; moveLegend(chartFullWidth * (pickerDelegate.pickerStart) - HORIZONTAL_PADDING); + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } public long getStartDate() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index d71d58c2f..90733bd51 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -36,6 +36,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; @@ -184,6 +185,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.PhonebookShareAlert; +import org.telegram.ui.Components.PinnedLineView; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.PollVotesAlert; import org.telegram.ui.Components.RLottieDrawable; @@ -213,6 +215,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.concurrent.CountDownLatch; import java.util.regex.Matcher; @@ -249,7 +252,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ClippingImageView animatingImageView; private RecyclerListView chatListView; private ChatListItemAnimator chatListItemAniamtor; - private int chatListViewClipTop; private GridLayoutManagerFixed chatLayoutManager; private ChatActivityAdapter chatAdapter; private UnreadCounterTextView bottomOverlayChatText; @@ -320,12 +322,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet voiceHintAnimation; private View emojiButtonRed; private FrameLayout pinnedMessageView; - private View pinnedLineView; + private View blurredView; + private PinnedLineView pinnedLineView; + private boolean setPinnedTextTranslationX; private AnimatorSet pinnedMessageViewAnimator; - private BackupImageView pinnedMessageImageView; - private SimpleTextView pinnedMessageNameTextView; + private BackupImageView[] pinnedMessageImageView = new BackupImageView[2]; + private SimpleTextView[] pinnedNameTextView = new SimpleTextView[2]; + private SimpleTextView[] pinnedMessageTextView = new SimpleTextView[2]; + private NumberTextView pinnedCounterTextView; + private int pinnedCounterTextViewX; + private AnimatorSet[] pinnedNextAnimation = new AnimatorSet[2]; private ImageView closePinned; - private SimpleTextView pinnedMessageTextView; + private ImageView pinnedListButton; + private AnimatorSet pinnedListAnimator; private FrameLayout alertView; private Runnable hideAlertViewRunnable; private TextView alertNameTextView; @@ -351,8 +360,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean checkTextureViewPosition; private boolean searchingForUser; private TLRPC.User searchingUserMessages; + private TLRPC.Chat searchingChatMessages; private UndoView undoView; private UndoView topUndoView; + private Bulletin pinBulletin; + private boolean showPinBulletin; + private int pinBullerinTag; private boolean openKeyboardOnAttachMenuClose; private MessageObject hintMessageObject; @@ -362,11 +375,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessagesSearchAdapter messagesSearchAdapter; private AnimatorSet messagesSearchListViewAnimation; - private boolean inScheduleMode; + public static final int MODE_SCHEDULED = 1; + public static final int MODE_PINNED = 2; + + private int chatMode; private int scheduledMessagesCount = -1; private MessageObject threadMessageObject; - private boolean replyMessageVisible = true; + private boolean threadMessageVisible = true; private ArrayList threadMessageObjects; private MessageObject replyMessageHeaderObject; private int threadMessageId; @@ -406,8 +422,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int mentionListViewLastViewPosition; private boolean mentionListViewIsScrolling; - private MessageObject pinnedMessageObject; - private int loadingPinnedMessage; + private ArrayList pinnedMessageIds = new ArrayList<>(); + private HashMap pinnedMessageObjects = new HashMap<>(); + private SparseArray loadingPinnedMessages = new SparseArray<>(); + private int currentPinnedMessageId; + private int[] currentPinnedMessageIndex = new int[1]; + private int forceNextPinnedMessageId; + private boolean forceScrollToFirst; + private int loadedPinnedMessagesCount; + private int totalPinnedMessagesCount; + private boolean loadingPinnedMessagesList; + private boolean pinnedEndReached; private AnimatorSet pagedownButtonAnimation; private ObjectAnimator mentiondownButtonAnimation; @@ -480,6 +505,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int cantForwardMessagesCount; private int canForwardMessagesCount; private int canEditMessagesCount; + private int cantSaveMessagesCount; + private int canSaveMusicCount; + private int canSaveDocumentsCount; private ArrayList waitingForLoad = new ArrayList<>(); private boolean needRemovePreviousSameChatActivity = true; @@ -557,6 +585,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Paint scrimPaint; private View scrimView; + private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; private ActionBarPopupWindow scrimPopupWindow; private ActionBarMenuSubItem[] scrimPopupWindowItems; @@ -564,6 +593,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ChatActivityDelegate chatActivityDelegate; private RecyclerAnimationScrollHelper chatScrollHelper; + private int postponedScrollMinMessageId; private int postponedScrollToLastMessageQueryIndex; private int postponedScrollMessageId; private boolean postponedScrollIsCanceled; @@ -591,6 +621,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int distanceToPeer; private int chatListViewPaddingTop; + private int contentPaddingTop; private float contentPanTranslation; private float floatingDateViewOffset; @@ -609,7 +640,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.commentsRead, NotificationCenter.messagesReadEncrypted, NotificationCenter.messagesReadContent, - NotificationCenter.pinnedMessageDidLoad, + NotificationCenter.commentsRead, + NotificationCenter.didLoadPinnedMessages, NotificationCenter.newDraftReceived, NotificationCenter.updateMentionsCount, NotificationCenter.didUpdateConnectionState, @@ -618,6 +650,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.contactsDidLoad, NotificationCenter.chatInfoCantLoad, NotificationCenter.userInfoDidLoad, + NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, NotificationCenter.didApplyNewTheme }; @@ -635,11 +668,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; private int chatEmojiViewPadding; + private int fixedKeyboardHeight = -1; + private boolean invalidateMessagesVisiblePart; + + public int getChatListViewPadding() { + return chatListViewPaddingTop; + } private interface ChatActivityDelegate { void openReplyMessage(int mid); void openSearch(String text); + + default void onUnpin(boolean all, boolean hide) { + + } } private class UnreadCounterTextView extends View { @@ -913,10 +956,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatActionCell && currentChat != null) { object.dialogId = -currentChat.id; } - if (pinnedMessageView != null && pinnedMessageView.getTag() == null || topChatPanelView != null && topChatPanelView.getTag() == null) { - object.clipTopAddition = AndroidUtilities.dp(48); - } - object.clipTopAddition += chatListViewClipTop; + object.clipTopAddition = chatListViewPaddingTop - AndroidUtilities.dp(4); return object; } } @@ -983,6 +1023,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int star = 22; private final static int edit = 23; private final static int add_shortcut = 24; + private final static int save_to = 25; private final static int bot_help = 30; private final static int bot_settings = 31; @@ -1085,7 +1126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not final int chatId = arguments.getInt("chat_id", 0); final int userId = arguments.getInt("user_id", 0); final int encId = arguments.getInt("enc_id", 0); - inScheduleMode = arguments.getBoolean("scheduled", false); + chatMode = arguments.getInt("chatMode", 0); inlineReturn = arguments.getLong("inline_return", 0); String inlineQuery = arguments.getString("inline_query"); startLoadFromMessageId = arguments.getInt("message_id", 0); @@ -1197,7 +1238,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addPostponeNotificationsCallback(postponeNotificationsWhileLoadingCallback); - if (!inScheduleMode) { + if (chatMode != MODE_SCHEDULED) { if (threadMessageId == 0) { getNotificationCenter().addObserver(this, NotificationCenter.screenshotTook); getNotificationCenter().addObserver(this, NotificationCenter.encryptedChatUpdated); @@ -1207,7 +1248,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().addObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.peerSettingsDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.pinnedMessageDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.didLoadPinnedMessages); getNotificationCenter().addObserver(this, NotificationCenter.commentsRead); getNotificationCenter().addObserver(this, NotificationCenter.changeRepliesCounter); getNotificationCenter().addObserver(this, NotificationCenter.messagesRead); @@ -1228,7 +1269,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateConnectionState); getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); - getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); + if (chatMode != MODE_PINNED) { + getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); + } getNotificationCenter().addObserver(this, NotificationCenter.closeChats); getNotificationCenter().addObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().addObserver(this, NotificationCenter.historyCleared); @@ -1254,6 +1297,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addObserver(this, NotificationCenter.botInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoCantLoad); getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.pinnedInfoDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didApplyNewTheme); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.goingToPreviewTheme); @@ -1266,30 +1310,50 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.onFragmentCreate(); - loading = true; + if (chatMode == MODE_PINNED) { + ArrayList messageObjects = new ArrayList<>(); + for (int a = 0, N = pinnedMessageIds.size(); a < N; a++) { + Integer id = pinnedMessageIds.get(a); + MessageObject object = pinnedMessageObjects.get(id); + if (object != null) { + MessageObject o = new MessageObject(object.currentAccount, object.messageOwner, true, false); + o.replyMessageObject = object.replyMessageObject; + o.mediaExists = object.mediaExists; + o.attachPathExists = object.attachPathExists; + messageObjects.add(o); + } + } + int loadIndex = lastLoadIndex++; + waitingForLoad.add(loadIndex); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, messageObjects.size(), messageObjects, false, 0, last_message_id, 0, 0, 2, true, classGuid, loadIndex, pinnedMessageIds.get(0), 0, MODE_PINNED); + } else { + loading = true; + } if (isThreadChat()) { if (highlightMessageId == startLoadFromMessageId) { needSelectFromMessageId = true; } - } else if (!inScheduleMode) { - if (currentEncryptedChat == null) { - getMediaDataController().loadBotKeyboard(dialog_id); - } - getMessagesController().loadPeerSettings(currentUser, currentChat); - getMessagesController().setLastCreatedDialogId(dialog_id, inScheduleMode, true); - - if (startLoadFromMessageId == 0) { - SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); - int messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); - if (messageId != 0) { - wasManualScroll = true; - loadingFromOldPosition = true; - startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + dialog_id, 0); - startLoadFromMessageId = messageId; + } else { + getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, true); + if (chatMode == 0) { + if (currentEncryptedChat == null) { + getMediaDataController().loadBotKeyboard(dialog_id); + } + getMessagesController().loadPeerSettings(currentUser, currentChat); + + if (startLoadFromMessageId == 0) { + SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); + int messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); + if (messageId != 0) { + wasManualScroll = true; + loadingFromOldPosition = true; + startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + dialog_id, 0); + startLoadFromMessageId = messageId; + } + } else { + showScrollToMessageError = true; + needSelectFromMessageId = true; } - } else { - showScrollToMessageError = true; - needSelectFromMessageId = true; } } @@ -1299,39 +1363,45 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentChat.megagroup && !getMessagesController().isChannelAdminsLoaded(currentChat.id)) { getMessagesController().loadChannelAdmins(currentChat.id, true); } - getMessagesStorage().loadChatInfo(currentChat.id, null, true, false); - if (!inScheduleMode && chatInfo != null && ChatObject.isChannel(currentChat) && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { + if (chatMode != MODE_PINNED) { + getMessagesStorage().loadChatInfo(currentChat.id, ChatObject.isChannel(currentChat), null, true, false, startLoadFromMessageId); + } + if (chatMode == 0 && chatInfo != null && ChatObject.isChannel(currentChat) && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; } loadInfo = chatInfo == null; } else if (currentUser != null) { - getMessagesController().loadUserInfo(currentUser, true, classGuid); + if (chatMode != MODE_PINNED) { + getMessagesController().loadUserInfo(currentUser, true, classGuid, startLoadFromMessageId); + } loadInfo = userInfo == null; } - waitingForLoad.add(lastLoadIndex); - if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId)) { - startLoadFromMessageIdSaved = startLoadFromMessageId; - if (migrated_to != 0) { - mergeDialogId = migrated_to; - getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + if (chatMode != MODE_PINNED) { + waitingForLoad.add(lastLoadIndex); + if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId)) { + startLoadFromMessageIdSaved = startLoadFromMessageId; + if (migrated_to != 0) { + mergeDialogId = migrated_to; + getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + } else { + getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + } } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); - } - } else { - if (historyPreloaded) { - lastLoadIndex++; - } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + if (historyPreloaded) { + lastLoadIndex++; + } else { + getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + } } } - if (!inScheduleMode && !isThreadChat()) { + if (chatMode == 0 && !isThreadChat()) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), true, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++); } - if (!inScheduleMode) { + if (chatMode == 0) { if (userId != 0 && currentUser.bot) { getMediaDataController().loadBotInfo(userId, true, classGuid); } else if (chatInfo instanceof TLRPC.TL_chatFull) { @@ -1389,6 +1459,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } + private void hideUndoViews() { + if (undoView != null) { + undoView.hide(true, 0); + } + if (pinBulletin != null) { + pinBulletin.hide(false); + } + if (topUndoView != null) { + topUndoView.hide(true, 0); + } + } + @Override public void onFragmentDestroy() { super.onFragmentDestroy(); @@ -1404,18 +1486,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatAttachAlert != null) { chatAttachAlert.dismissInternal(); } - if (undoView != null) { - undoView.hide(true, 0); - } - if (topUndoView != null) { - topUndoView.hide(true, 0); - } + hideUndoViews(); if (chatInviteRunnable != null) { AndroidUtilities.cancelRunOnUIThread(chatInviteRunnable); chatInviteRunnable = null; } getNotificationCenter().removePostponeNotificationsCallback(postponeNotificationsWhileLoadingCallback); - getMessagesController().setLastCreatedDialogId(dialog_id, inScheduleMode, false); + getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, false); getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateConnectionState); @@ -1458,10 +1535,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingPlayStateChanged); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateMessagesViews); getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoCantLoad); - getNotificationCenter().removeObserver(this, NotificationCenter.pinnedMessageDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.didLoadPinnedMessages); getNotificationCenter().removeObserver(this, NotificationCenter.peerSettingsDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.pinnedInfoDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didApplyNewTheme); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.goingToPreviewTheme); @@ -1478,7 +1556,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().removeObserver(this, NotificationCenter.didVerifyMessagesStickers); } - if (!inScheduleMode && AndroidUtilities.isTablet()) { + if (chatMode == 0 && AndroidUtilities.isTablet()) { getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); } if (currentUser != null) { @@ -1533,12 +1611,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } + scheduledOrNoSoundHint = null; + distanseTopView = null; + aspectRatioFrameLayout = null; + videoTextureView = null; + searchAsListHint = null; + mediaBanTooltip = null; + noSoundHintView = null; + forwardHintView = null; + textSelectionHint = null; + emojiButtonRed = null; + gifHintTextView = null; + pollHintView = null; + videoPlayerContainer = null; + voiceHintTextView = null; + blurredView = null; + dummyMessageCell = null; cantDeleteMessagesCount = 0; canEditMessagesCount = 0; cantForwardMessagesCount = 0; canForwardMessagesCount = 0; - videoPlayerContainer = null; - voiceHintTextView = null; + cantSaveMessagesCount = 0; + canSaveMusicCount = 0; + canSaveDocumentsCount = 0; hasOwnBackground = true; if (chatAttachAlert != null) { @@ -1611,6 +1706,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not createDeleteMessagesAlert(null, null); } else if (id == forward) { openForward(); + } else if (id == save_to) { + ArrayList messageObjects = new ArrayList<>(); + for (int a = 1; a >= 0; a--) { + for (int b = 0; b < selectedMessagesIds[a].size(); b++) { + messageObjects.add(selectedMessagesIds[a].valueAt(b)); + } + selectedMessagesIds[a].clear(); + selectedMessagesCanCopyIds[a].clear(); + selectedMessagesCanStarIds[a].clear(); + } + boolean isMusic = canSaveMusicCount > 0; + hideActionMode(); + updatePinnedMessageView(true); + updateVisibleRows(); + MediaController.saveFilesFromMessages(getParentActivity(), getAccountInstance(), messageObjects, (count) -> { + if (count > 0) { + BulletinFactory.of(ChatActivity.this).createDownloadBulletin(isMusic ? BulletinFactory.FileType.AUDIOS : BulletinFactory.FileType.UNKNOWNS, count).show(); + } + }); } else if (id == chat_enc_timer) { if (getParentActivity() == null) { return; @@ -1633,14 +1747,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat, param); } else { clearingHistory = true; - undoView.showWithAction(dialog_id, id == clear_history ? UndoView.ACTION_CLEAR : UndoView.ACTION_DELETE, () -> { - if (chatInfo != null && chatInfo.pinned_msg_id != 0) { + undoView.showWithAction(dialog_id, UndoView.ACTION_CLEAR, () -> { + if (!pinnedMessageIds.isEmpty()) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).commit(); - updatePinnedMessageView(true); - } else if (userInfo != null && userInfo.pinned_msg_id != 0) { - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); + pinnedMessageIds.clear(); + pinnedMessageObjects.clear(); + currentPinnedMessageId = 0; + loadedPinnedMessagesCount = 0; + totalPinnedMessagesCount = 0; updatePinnedMessageView(true); } getMessagesController().deleteDialog(dialog_id, 1, param); @@ -1764,11 +1879,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (inPreviewMode || inBubbleMode) { avatarContainer.setOccupyStatusBar(false); } - actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0)); + actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : (chatMode == MODE_PINNED ? 10 : 0), 0, 40, 0)); ActionBarMenu menu = actionBar.createMenu(); - if (currentEncryptedChat == null && !inScheduleMode) { + if (currentEncryptedChat == null && chatMode == 0) { searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { boolean searchWas; @@ -1795,6 +1910,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionLayoutManager.setReverseLayout(false); mentionsAdapter.setSearchingMentions(false); searchingUserMessages = null; + searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); searchItem.setSearchFieldCaption(null); avatarContainer.setVisibility(View.VISIBLE); @@ -1863,7 +1979,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); + getMediaDataController().searchMessagesInChat(editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } @Override @@ -1871,14 +1987,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showMessagesSearchListView(false); if (searchingForUser) { mentionsAdapter.searchUsernameOrHashtag("@" + editText.getText().toString(), 0, messages, true); - } else if (!searchingForUser && searchingUserMessages == null && searchUserButton != null && TextUtils.equals(editText.getText(), LocaleController.getString("SearchFrom", R.string.SearchFrom))) { + } else if (searchingUserMessages == null && searchingChatMessages == null && searchUserButton != null && TextUtils.equals(editText.getText(), LocaleController.getString("SearchFrom", R.string.SearchFrom))) { searchUserButton.callOnClick(); } } @Override public void onCaptionCleared() { - if (searchingUserMessages != null) { + if (searchingUserMessages != null || searchingChatMessages != null) { searchUserButton.callOnClick(); } else { if (searchingForUser) { @@ -1890,6 +2006,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchCalendarButton.setVisibility(View.VISIBLE); searchUserButton.setVisibility(View.VISIBLE); searchingUserMessages = null; + searchingChatMessages = null; } } @@ -1905,7 +2022,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchItemVisible = false; } - if (!inScheduleMode && threadMessageId == 0 && !UserObject.isReplyUser(currentUser)) { + if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser)) { headerItem = menu.addItem(0, R.drawable.ic_ab_other); headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); if (currentUser != null) { @@ -1940,7 +2057,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_mono, stringBuilder); - if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { + if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; @@ -1967,7 +2084,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat != null) { timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.msg_timer, LocaleController.getString("SetTimer", R.string.SetTimer)); } - if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup && TextUtils.isEmpty(currentChat.username)) { + if (!ChatObject.isChannel(currentChat) || currentChat.megagroup && TextUtils.isEmpty(currentChat.username)) { headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); } if (currentUser == null || !currentUser.self) { @@ -2003,7 +2120,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer.updateSubtitle(); updateTitleIcons(); - if (!inScheduleMode && !isThreadChat()) { + if (chatMode == 0 && !isThreadChat()) { attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false); attachItem.setVisibility(View.GONE); } @@ -2029,6 +2146,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); 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))); @@ -2072,6 +2190,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onTransitionStart(boolean keyboardVisible) { + wasManualScroll = true; if (chatActivityEnterView != null) { chatActivityEnterView.onAdjustPanTransitionStart(keyboardVisible); } @@ -2088,12 +2207,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { actionBar.setTranslationY(y); emptyViewContainer.setTranslationY(y / 2); + progressView.setTranslationY(y / 2); contentView.setBackgroundTranslation((int) y); instantCameraView.onPanTranslationUpdate(y); setFragmentPanTranslationOffset((int) y); invalidateChatListViewTopPadding(); + invalidateMessagesVisiblePart(); } - updateChatListViewTopPadding(); chatListView.setItemAnimator(null); chatListView.invalidate(); } @@ -2101,7 +2221,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected boolean heightAnimationEnabled() { ActionBarLayout actionBarLayout = getParentLayout(); - if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null) { + if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { return false; } if (System.currentTimeMillis() - activityResumeTime < 250) { @@ -2148,7 +2268,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean dispatchTouchEvent(MotionEvent ev) { float expandY; if (AndroidUtilities.isInMultiwindow || isInBubbleMode()) { - expandY = chatActivityEnterView != null && chatActivityEnterView.getEmojiView() != null ? chatActivityEnterView.getEmojiView().getY() : chatActivityEnterView.getY(); + expandY = chatActivityEnterView.getEmojiView() != null ? chatActivityEnterView.getEmojiView().getY() : chatActivityEnterView.getY(); } else { expandY = chatActivityEnterView.getY(); } @@ -2252,7 +2372,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { drawLaterRoundProgressCell.drawOverlays(canvas); if (drawLaterRoundProgressCell.needDrawTime()) { - drawLaterRoundProgressCell.drawTime(canvas, drawLaterRoundProgressCell.getAlpha()); + drawLaterRoundProgressCell.drawTime(canvas, drawLaterRoundProgressCell.getAlpha(), true); } } canvas.restore(); @@ -2277,19 +2397,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f; canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight()); canvas.translate(canvasOffsetX, canvasOffsetY); + cell.setInvalidatesParent(true); if (type == 0) { - cell.drawTime(canvas, alpha); + cell.drawTime(canvas, alpha, true); } else if (type == 1) { cell.drawNamesLayout(canvas, alpha); } else { cell.drawCaptionLayout(canvas, (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0, alpha); } + cell.setInvalidatesParent(false); canvas.restore(); } @Override protected void dispatchDraw(Canvas canvas) { + chatActivityEnterView.checkAnimation(); updateChatListViewTopPadding(); + if (invalidateMessagesVisiblePart || (chatListItemAniamtor != null && chatListItemAniamtor.isRunning())) { + invalidateMessagesVisiblePart = false; + updateMessagesVisiblePart(false); + } super.dispatchDraw(canvas); if (chatActivityEnterView != null) { if (chatActivityEnterView.pannelAniamationInProgress() && chatActivityEnterView.getEmojiPadding() < bottomPanelTranslationY) { @@ -2307,11 +2434,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (scrimView != null) { canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); - int chatListViewTop = (int) chatListView.getY(); - int chatListViewBottom = chatListViewTop + chatListView.getMeasuredHeight(); - float listTop = chatListView.getTop() + chatListView.getPaddingTop() - AndroidUtilities.dp(4); - if (threadMessageId != 0 && !replyMessageVisible) { - listTop += AndroidUtilities.dp(48); + float listTop = chatListView.getY() + chatListViewPaddingTop - AndroidUtilities.dp(4); + if (isThreadChat()) { + float pinnedViewH = 0; + if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); + } + listTop += pinnedViewH; } MessageObject.GroupedMessages scrimGroup; if (scrimView instanceof ChatMessageCell) { @@ -2341,54 +2470,39 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not continue; } - if (!groupedBackgroundWasDraw && cell != null && scrimGroup != null) { - float x = cell.getNonAnimationTranslationX(true); + if (!groupedBackgroundWasDraw && cell != null && scrimGroup != null && scrimGroup.transitionParams.cell != null) { + float x = scrimGroup.transitionParams.cell.getNonAnimationTranslationX(true); + float l = (scrimGroup.transitionParams.left + x + scrimGroup.transitionParams.offsetLeft); - float t = (scrimGroup.transitionParams.top + scrimGroup.transitionParams.offsetTop + chatListView.getY()); + float t = (scrimGroup.transitionParams.top + scrimGroup.transitionParams.offsetTop); float r = (scrimGroup.transitionParams.right + x + scrimGroup.transitionParams.offsetRight); - float b = (scrimGroup.transitionParams.bottom + scrimGroup.transitionParams.offsetBottom + chatListView.getY()); + float b = (scrimGroup.transitionParams.bottom + scrimGroup.transitionParams.offsetBottom); if (!scrimGroup.transitionParams.backgroundChangeBounds) { - t += cell.getTranslationY(); - b += cell.getTranslationY(); + t += scrimGroup.transitionParams.cell.getTranslationY(); + b += scrimGroup.transitionParams.cell.getTranslationY(); } + + if (t < chatListViewPaddingTop - AndroidUtilities.dp(20)) { + t = chatListViewPaddingTop - AndroidUtilities.dp(20); + } + + if (b > chatListView.getMeasuredHeight() + AndroidUtilities.dp(20)) { + b = chatListView.getMeasuredHeight() + AndroidUtilities.dp(20); + } + canvas.save(); canvas.clipRect(0, listTop, getMeasuredWidth(), chatListView.getY() + chatListView.getHeight()); - cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, scrimGroup.transitionParams.pinnedTop, scrimGroup.transitionParams.pinnedBotton); + canvas.translate(0, chatListView.getY()); + scrimGroup.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, scrimGroup.transitionParams.pinnedTop, scrimGroup.transitionParams.pinnedBotton); canvas.restore(); groupedBackgroundWasDraw = true; } - int clipLeft = 0; - int clipBottom = 0; - - float viewClipLeft; - float viewClipRight; - float viewClipTop; - float viewClipBottom; - - if (clipLeft != 0) { - float x = chatListView.getLeft() + clipLeft + child.getTranslationX(); - float y = chatListView.getTop() + child.getTop(); - - viewClipLeft = Math.max(chatListView.getLeft(), x); - viewClipTop = Math.max(listTop, y); - viewClipRight = Math.min(chatListView.getRight(), x + child.getMeasuredWidth()); - viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getTop() + child.getMeasuredHeight()); - } else if (clipBottom != 0) { - float x = chatListView.getLeft() + child.getTranslationX(); - float y = chatListView.getTop() + child.getTop(); - - viewClipLeft = Math.max(chatListView.getLeft(), x); - viewClipTop = Math.max(listTop, y); - viewClipRight = Math.min(chatListView.getRight(), x + child.getMeasuredWidth()); - viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + clipBottom); - } else { - viewClipLeft = Math.max(chatListView.getLeft(), chatListView.getLeft() + child.getX()); - viewClipTop = Math.max(listTop, chatListView.getTop() + child.getY()); - viewClipRight = Math.min(chatListView.getRight(), chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); - viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getY() + child.getMeasuredHeight()); - } + float viewClipLeft = Math.max(chatListView.getLeft(), chatListView.getLeft() + child.getX()); + float viewClipTop = Math.max(listTop, chatListView.getTop() + child.getY()); + float viewClipRight = Math.min(chatListView.getRight(), chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); + float viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getY() + child.getMeasuredHeight()); if (viewClipTop < viewClipBottom) { if (child.getAlpha() != 1f) { @@ -2396,22 +2510,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { canvas.save(); } + if (cell != null) { + cell.setInvalidatesParent(true); + } canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); child.draw(canvas); canvas.restore(); + + if (cell != null) { + cell.setInvalidatesParent(false); + } } - if (position != null) { - if (position.last || position.minX == 0 && position.minY == 0) { - if (position.last) { + if (position != null || cell != null && cell.getTransitionParams().animateBackgroundBoundsInner) { + if (position == null || position.last || position.minX == 0 && position.minY == 0) { + if (position == null || position.last) { drawTimeAfter.add(cell); } - if (position.minX == 0 && position.minY == 0 && cell.hasNameLayout()) { + if (position == null || (position.minX == 0 && position.minY == 0 && cell.hasNameLayout())) { drawNamesAfter.add(cell); } } - if ((cell.hasCaptionLayout() || cell.hasCommentLayout()) && (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + if ((cell.hasCaptionLayout() || cell.hasCommentLayout()) && (position == null || (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0)) { drawCaptionAfter.add(cell); } } @@ -2456,6 +2577,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.drawChild(canvas, fireworksOverlay, SystemClock.uptimeMillis()); } } + if (fixedKeyboardHeight > 0 && keyboardHeight < AndroidUtilities.dp(20)) { + int color = Theme.getColor(Theme.key_windowBackgroundWhite); + if (backgroundPaint == null) { + backgroundPaint = new Paint(); + } + if (backgroundColor != color) { + backgroundPaint.setColor(backgroundColor = color); + } + canvas.drawRect(0,getMeasuredHeight() - fixedKeyboardHeight, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); + } } @Override @@ -2467,10 +2598,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setMeasuredDimension(widthSize, heightSize); heightSize -= getPaddingTop(); -// if (SharedConfig.smoothKeyboard && chatActivityEnterView.isPopupShowing()) { -// setNonNoveTranslation(0); -// } - measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); int actionBarHeight = actionBar.getMeasuredHeight(); if (actionBar.getVisibility() == VISIBLE) { @@ -2481,19 +2608,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not measureKeyboardHeight(); } int keyboardSize = getKeyboardHeight(); - - if (keyboardSize <= AndroidUtilities.dp(20)) { - if (!inBubbleMode && !AndroidUtilities.isInMultiwindow && !SharedConfig.smoothKeyboard) { - heightSize -= chatActivityEnterView.getEmojiPadding(); - allHeight -= chatActivityEnterView.getEmojiPadding(); - chatEmojiViewPadding = 0; - } else { - chatEmojiViewPadding = chatActivityEnterView.isPopupShowing() ? chatActivityEnterView.getEmojiPadding() : 0; - } + if (fixedKeyboardHeight > 0 && keyboardSize <= AndroidUtilities.dp(20)) { + chatEmojiViewPadding = fixedKeyboardHeight; } else { - chatEmojiViewPadding = 0; + if (keyboardSize <= AndroidUtilities.dp(20)) { + chatEmojiViewPadding = chatActivityEnterView.isPopupShowing() ? chatActivityEnterView.getEmojiPadding() : 0; + } else { + chatEmojiViewPadding = 0; + } } - invalidateChatListViewTopPadding(); int childCount = getChildCount(); @@ -2512,8 +2635,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (child == null || child.getVisibility() == GONE || child == chatActivityEnterView || child == actionBar) { continue; } - if (child == chatListView) { - chatListViewClipTop = inPreviewMode ? 0 : (inputFieldHeight - AndroidUtilities.dp(51)); + if (child == blurredView) { + int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); + int contentHeightSpec = MeasureSpec.makeMeasureSpec(allHeight, MeasureSpec.EXACTLY); + child.measure(contentWidthSpec, contentHeightSpec); + } else if (child == chatListView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { @@ -2604,7 +2730,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (fixPaddingsInLayout) { globalIgnoreLayout = true; - checkListViewPaddingsInternal(); + invalidateChatListViewTopPadding(); fixPaddingsInLayout = false; chatListView.measure(MeasureSpec.makeMeasureSpec(chatListView.getMeasuredWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(chatListView.getMeasuredHeight(), MeasureSpec.EXACTLY)); globalIgnoreLayout = false; @@ -2628,7 +2754,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); int keyboardSize = getKeyboardHeight(); - int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : 0; + int paddingBottom; + if (fixedKeyboardHeight > 0 && keyboardSize <= AndroidUtilities.dp(20)) { + paddingBottom = fixedKeyboardHeight; + } else { + paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : 0; + } if (!SharedConfig.smoothKeyboard) { setBottomClip(paddingBottom); } @@ -2686,7 +2817,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not childTop = lp.topMargin; } - if (child instanceof HintView) { + if (child == blurredView) { + childTop = 0; + } else if (child instanceof HintView) { childTop = 0; } else if (child == mentionContainer) { childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); @@ -2712,9 +2845,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!inPreviewMode) { childTop -= (inputFieldHeight - AndroidUtilities.dp(51)); } - if (SharedConfig.smoothKeyboard) { - childTop -= paddingBottom; - } + + childTop -= paddingBottom; + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } @@ -2729,18 +2862,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not childTop -= getPaddingTop(); } else if (child == videoPlayerContainer) { childTop = actionBar.getMeasuredHeight(); - if (SharedConfig.smoothKeyboard) { - childTop -= paddingBottom; - } + childTop -= paddingBottom; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } } else if (child == instantCameraView || child == overlayView || child == animatingImageView) { childTop = 0; } else if (child == textSelectionHelper.getOverlayView(context)) { - if (SharedConfig.smoothKeyboard) { - childTop -= paddingBottom; - } + childTop -= paddingBottom; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } @@ -2748,7 +2877,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not child.layout(childLeft, childTop, childLeft + width, childTop + height); } - updateMessagesVisiblePart(true); + invalidateChatListViewTopPadding(); + invalidateMessagesVisiblePart(); updateTextureViewPosition(false); if (!scrollingChatListView) { @@ -2761,6 +2891,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.setTranslationY(y); actionBar.setTranslationY(0); emptyViewContainer.setTranslationY(0); + progressView.setTranslationY(0); contentPanTranslation = 0; contentView.setBackgroundTranslation(0); instantCameraView.onPanTranslationUpdate(0); @@ -2796,7 +2927,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0)); } else if (currentEncryptedChat == null) { - if (!isThreadChat() && !inScheduleMode && (currentUser != null && currentUser.self || currentChat != null && currentChat.creator)) { + if (!isThreadChat() && chatMode == 0 && (currentUser != null && currentUser.self || currentChat != null && currentChat.creator)) { bigEmptyView = new ChatBigEmptyView(context, currentChat != null ? ChatBigEmptyView.EMPTY_VIEW_TYPE_GROUP : ChatBigEmptyView.EMPTY_VIEW_TYPE_SAVED); emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); if (currentChat != null) { @@ -2810,7 +2941,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { emptyView.setText(LocaleController.getString("NoReplies", R.string.NoReplies)); } - } else if (inScheduleMode) { + } else if (chatMode == MODE_SCHEDULED) { emptyView.setText(LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages)); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); @@ -2869,7 +3000,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean wasTrackingVibrate; private float replyButtonProgress; private long lastReplyButtonAnimationTime; - private float cilpTop; private boolean ignoreLayout; @@ -2887,12 +3017,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void setTranslationY(float translationY) { super.setTranslationY(translationY); if (emptyViewContainer != null) { - emptyViewContainer.setTranslationY(translationY / 2f); + emptyViewContainer.setTranslationY(translationY / 1.7f); } invalidate(); } - @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); @@ -2926,7 +3055,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int count = getChildCount(); for (int a = 0; a < count; a++) { View child = getChildAt(a); - if (child == this || !(child instanceof ChatMessageCell)) { + if (child == view || !(child instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) child; @@ -3035,13 +3164,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatMessageCell) { slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); - if (inScheduleMode || threadMessageObjects != null && threadMessageObjects.contains(message) || + if (chatMode != 0 || threadMessageObjects != null && threadMessageObjects.contains(message) || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat)) || textSelectionHelper.isSelectionMode()) { + slidingView.setSlidingOffset(0); slidingView = null; return; } @@ -3129,7 +3259,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected void onChildPressed(View child, float x, float y, boolean pressed) { super.onChildPressed(child, x, y, pressed); if (child instanceof ChatMessageCell) { - MessageObject.GroupedMessages groupedMessages = ((ChatMessageCell) child).getCurrentMessagesGroup(); + ChatMessageCell chatMessageCell = (ChatMessageCell) child; + MessageObject object = chatMessageCell.getMessageObject(); + if (object.isMusic() || object.isDocument()) { + return; + } + MessageObject.GroupedMessages groupedMessages = chatMessageCell.getCurrentMessagesGroup(); if (groupedMessages != null) { int count = getChildCount(); for (int a = 0; a < count; a++) { @@ -3138,7 +3273,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not continue; } ChatMessageCell cell = (ChatMessageCell) item; - if (((ChatMessageCell) item).getCurrentMessagesGroup() == groupedMessages) { + if (cell.getCurrentMessagesGroup() == groupedMessages) { cell.setPressed(pressed); } } @@ -3171,6 +3306,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (trackAnimationProgress == 1f || trackAnimationProgress == 0f) { + slidingView.setSlidingOffset(0); slidingView = null; } invalidate(); @@ -3191,11 +3327,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject.GroupedMessages lastDrawnGroup = null; int count = getChildCount(); + canvas.save(); + canvas.clipRect(0, chatListViewPaddingTop - AndroidUtilities.dp(4), getMeasuredWidth(), getMeasuredHeight()); + for (int a = 0; a < count; a++) { View child = getChildAt(a); if (chatAdapter.isBot && child instanceof BotHelpCell) { BotHelpCell botCell = (BotHelpCell) child; - int top = getMeasuredHeight() / 2 - child.getMeasuredHeight() / 2 + chatListView.getPaddingTop(); + int top = getMeasuredHeight() / 2 - child.getMeasuredHeight() / 2 + chatListViewPaddingTop; if (!botCell.animating() && !chatListView.fastScrollAnimationRunning) { if (child.getTop() > top) { child.setTranslationY(top - child.getTop()); @@ -3281,14 +3420,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; - if (chatListView.isFastScrollAnimationRunning()) { - if (child.getY() > chatListView.getHeight() || child.getY() + child.getHeight() < 0) { - continue; - } - } else { - if (child.getTop() > chatListView.getHeight() || child.getTop() + child.getHeight() < 0) { - continue; - } + if (child.getY() > chatListView.getHeight() || child.getY() + child.getHeight() < 0) { + continue; } MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (group == null || (k == 0 && group.messages.size() == 1) || (k == 1 && !group.transitionParams.drawBackgroundForDeletedItems)) { @@ -3313,19 +3446,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawingGroups.add(group); } - if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_TOP) != 0) { - group.transitionParams.pinnedTop = cell.isPinnedTop(); - } - if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { - group.transitionParams.pinnedBotton = cell.isPinnedBottom(); - } - + group.transitionParams.pinnedTop = cell.isPinnedTop(); + group.transitionParams.pinnedBotton = cell.isPinnedBottom(); int left = (cell.getLeft() + cell.getBackgroundDrawableLeft()); int right = (cell.getLeft() + cell.getBackgroundDrawableRight()); int top = (cell.getTop() + cell.getBackgroundDrawableTop()); int bottom = (cell.getTop() + cell.getBackgroundDrawableBottom()); + if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_TOP) == 0) { + top -= AndroidUtilities.dp(10); + } + + if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { + bottom += AndroidUtilities.dp(10); + } + if (cell.willRemovedAfterAnimation()) { group.transitionParams.cell = cell; } @@ -3348,7 +3484,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < drawingGroups.size(); i++) { MessageObject.GroupedMessages group = drawingGroups.get(i); if (group == scrimGroup) { - group.transitionParams.cell = null; continue; } float x = group.transitionParams.cell.getNonAnimationTranslationX(true); @@ -3362,6 +3497,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not b += group.transitionParams.cell.getTranslationY(); } + if (t < chatListViewPaddingTop - AndroidUtilities.dp(20)) { + t = chatListViewPaddingTop - AndroidUtilities.dp(20); + } + + if (b > chatListView.getMeasuredHeight() + AndroidUtilities.dp(20)) { + b = chatListView.getMeasuredHeight() + AndroidUtilities.dp(20); + } + boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; if (useScale) { canvas.save(); @@ -3385,12 +3528,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - canvas.save(); - cilpTop = actionBar.getY() + actionBar.getMeasuredHeight() - getY(); - if (pinnedMessageView != null) { - cilpTop += Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); - } - canvas.clipRect(0, cilpTop, getMeasuredWidth(), getMeasuredHeight()); super.dispatchDraw(canvas); canvas.restore(); } @@ -3401,6 +3538,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int clipBottom = 0; boolean skipDraw = child == scrimView; ChatMessageCell cell; + float cilpTop = chatListViewPaddingTop - AndroidUtilities.dp(4); if (child.getY() > getMeasuredHeight() || child.getY() + child.getMeasuredHeight() < cilpTop) { skipDraw = true; @@ -3428,15 +3566,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not skipDraw = true; } } + if (skipDraw) { + cell.getPhotoImage().skipDraw(); + } } else { cell = null; } if (clipLeft != 0) { canvas.save(); - //canvas.clipRect(clipLeft + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), child.getBottom()); } else if (clipBottom != 0) { canvas.save(); - //canvas.clipRect(child.getLeft() + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), clipBottom); } boolean result; if (!skipDraw) { @@ -3500,7 +3639,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cell = drawTimeAfter.get(a); canvas.save(); canvas.translate(cell.getLeft() + cell.getNonAnimationTranslationX(false), cell.getY()); - cell.drawTime(canvas, cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f); + cell.drawTime(canvas, cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f, true); canvas.restore(); } drawTimeAfter.clear(); @@ -3515,7 +3654,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not canvas.save(); canvas.translate(canvasOffsetX, canvasOffsetY); + cell.setInvalidatesParent(true); cell.drawNamesLayout(canvas, alpha); + cell.setInvalidatesParent(false); canvas.restore(); } drawNamesAfter.clear(); @@ -3574,12 +3715,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not float canvasOffsetY = chatMessageCell.getTop(); canvas.save(); canvas.translate(canvasOffsetX, canvasOffsetY); + cell.setInvalidatesParent(true); if (position == null || position.last) { - chatMessageCell.drawTime(canvas, alpha); + chatMessageCell.drawTime(canvas, alpha, true); } if (position == null || (position.minX == 0 && position.minY == 0)) { chatMessageCell.drawNamesLayout(canvas, alpha); } + cell.setInvalidatesParent(false); canvas.restore(); } else { if (position == null || position.last) { @@ -3630,7 +3773,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (videoPlayerContainer != null && (message.isRoundVideo() || message.isVideo()) && MediaController.getInstance().isPlayingMessage(message)) { ImageReceiver imageReceiver = chatMessageCell.getPhotoImage(); float newX = imageReceiver.getImageX() + chatMessageCell.getX(); - float newY = fragmentView.getPaddingTop() + chatMessageCell.getY() + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0); + float newY = fragmentView.getPaddingTop() + chatMessageCell.getY() + imageReceiver.getImageY() + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0); if (videoPlayerContainer.getTranslationX() != newX || videoPlayerContainer.getTranslationY() != newY) { videoPlayerContainer.setTranslationX(newX); videoPlayerContainer.setTranslationY(newY); @@ -3651,7 +3794,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean replaceAnimation = chatListView.isFastScrollAnimationRunning() || (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds); int top = replaceAnimation ? child.getTop() : (int) child.getY(); - if (chatMessageCell.isPinnedBottom()) { + if (chatMessageCell.drawPinnedBottom()) { int p; if (chatMessageCell.willRemovedAfterAnimation()) { p = chatScrollHelper.positionToOldView.indexOfValue(child); @@ -3716,7 +3859,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!replaceAnimation && child.getTranslationY() != 0) { canvas.restore(); } - if (chatMessageCell.isPinnedTop()) { + if (chatMessageCell.drawPinnedTop()) { int p; if (chatMessageCell.willRemovedAfterAnimation()) { p = chatScrollHelper.positionToOldView.indexOfValue(child); @@ -3763,7 +3906,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not top = view.getTop(); if (view instanceof ChatMessageCell) { cell = (ChatMessageCell) view; - if (!cell.isPinnedTop()) { + if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; @@ -3780,7 +3923,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not top = holder.itemView.getTop(); if (holder.itemView instanceof ChatMessageCell) { cell = (ChatMessageCell) holder.itemView; - if (!cell.isPinnedTop()) { + if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; @@ -3798,7 +3941,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (y - AndroidUtilities.dp(48) < top) { y = top + AndroidUtilities.dp(48); } - if (!chatMessageCell.isPinnedBottom()) { + if (!chatMessageCell.drawPinnedBottom()) { int cellBottom = replaceAnimation ? chatMessageCell.getBottom() : (int) (chatMessageCell.getY() + chatMessageCell.getMeasuredHeight()); if (y > cellBottom) { y = cellBottom; @@ -3872,6 +4015,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); chatListView.setAnimateEmptyView(true, 1); + chatListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); chatListViewPaddingTop = 0; invalidateChatListViewTopPadding(); if (MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)) { @@ -3883,7 +4027,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAnimationStart() { if (index == -1) { - index = getNotificationCenter().setAnimationInProgress(index, allowedNotificationsDuringChatListAnimations); + index = getNotificationCenter().setAnimationInProgress(index, allowedNotificationsDuringChatListAnimations, false); } if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); @@ -3933,6 +4077,70 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, true) { + + boolean computingScroll; + + @Override + public int getStarForFixGap() { + return chatListViewPaddingTop; + } + + @Override + protected int getParentStart() { + if (computingScroll) { + return chatListViewPaddingTop; + } + return 0; + } + + @Override + public int getStartAfterPadding() { + if (computingScroll) { + return chatListViewPaddingTop; + } + return super.getStartAfterPadding(); + } + + @Override + public int getTotalSpace() { + if (computingScroll) { + return getHeight() - chatListViewPaddingTop - getPaddingBottom(); + } + return super.getTotalSpace(); + } + + @Override + public int computeVerticalScrollExtent(RecyclerView.State state) { + computingScroll = true; + int r = super.computeVerticalScrollExtent(state); + computingScroll = false; + return r; + } + + @Override + public int computeVerticalScrollOffset(RecyclerView.State state) { + computingScroll = true; + int r = super.computeVerticalScrollOffset(state); + computingScroll = false; + return r; + } + + @Override + public int computeVerticalScrollRange(RecyclerView.State state) { + computingScroll = true; + int r = super.computeVerticalScrollRange(state); + computingScroll = false; + return r; + } + + @Override + public void scrollToPositionWithOffset(int position, int offset, boolean bottom) { + if (!bottom) { + offset = offset - getPaddingTop() + chatListViewPaddingTop; + } + super.scrollToPositionWithOffset(position, offset, bottom); + } + @Override public boolean supportsPredictiveItemAnimations() { return true; @@ -3995,6 +4203,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + + @Override + public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { + int n = chatListView.getChildCount(); + for (int i = 0; i < n; i++) { + View child = chatListView.getChildAt(i); + if (chatListView.getChildAdapterPosition(child) == chatAdapter.getItemCount() - 1) { + if (child.getTop() - dy > chatListViewPaddingTop) { + dy = child.getTop() - chatListViewPaddingTop; + } + return super.scrollVerticallyBy(dy, recycler, state); + } + } + return super.scrollVerticallyBy(dy, recycler, state); + } }; chatLayoutManager.setSpanSizeLookup(new GridLayoutManagerFixed.SpanSizeLookup() { @Override @@ -4094,8 +4317,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onScrolled(RecyclerView recyclerView, int dx, int dy) { chatListView.invalidate(); scrollUp = dy < 0; - if (!wasManualScroll && dy != 0 && recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { - wasManualScroll = true; + if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { + if ((!scrollUp || forceScrollToFirst) && forceNextPinnedMessageId != 0) { + forceNextPinnedMessageId = 0; + } + forceScrollToFirst = false; + if (!wasManualScroll && dy != 0) { + wasManualScroll = true; + } } if (dy != 0) { hideHints(true); @@ -4139,7 +4368,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - updateMessagesVisiblePart(true); + invalidateMessagesVisiblePart(); textSelectionHelper.onParentScrolled(); } }); @@ -4199,7 +4428,63 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); if (currentEncryptedChat == null) { - pinnedMessageView = new FrameLayout(context); + pinnedMessageView = new FrameLayout(context) { + + float lastY; + float startY; + + { + setOnLongClickListener(v -> { + if (AndroidUtilities.isTablet() || isThreadChat()) { + return false; + } + startY = lastY; + openPinnedMessagesList(true); + return true; + }); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + lastY = event.getY(); + if (event.getAction() == MotionEvent.ACTION_UP) { + finishPreviewFragment(); + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + float dy = startY - lastY; + movePreviewFragment(dy); + if (dy < 0) { + startY = lastY; + } + } + return super.onTouchEvent(event); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (setPinnedTextTranslationX) { + for (int a = 0; a < pinnedNextAnimation.length; a++) { + if (pinnedNextAnimation[a] != null) { + pinnedNextAnimation[a].start(); + } + } + setPinnedTextTranslationX = false; + } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == pinnedLineView) { + canvas.save(); + canvas.clipRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(48)); + } + boolean result = super.drawChild(canvas, child, drawingTime); + if (child == pinnedLineView) { + canvas.restore(); + } + return result; + } + }; pinnedMessageView.setTag(1); pinnedMessageEnterOffset = -AndroidUtilities.dp(50); pinnedMessageView.setVisibility(View.GONE); @@ -4207,13 +4492,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedMessageView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); contentView.addView(pinnedMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); pinnedMessageView.setOnClickListener(v -> { + if (chatListView.isFastScrollAnimationRunning()) { + return; + } wasManualScroll = true; if (isThreadChat()) { scrollToMessageId(threadMessageId, 0, true, 0, true); - } else if (chatInfo != null) { - scrollToMessageId(chatInfo.pinned_msg_id, 0, true, 0, true); - } else if (userInfo != null) { - scrollToMessageId(userInfo.pinned_msg_id, 0, true, 0, true); + } else if (currentPinnedMessageId != 0) { + scrollToMessageId(currentPinnedMessageId, 0, true, 0, true); + if (!pinnedMessageIds.isEmpty()) { + if (currentPinnedMessageId == pinnedMessageIds.get(pinnedMessageIds.size() - 1)) { + forceNextPinnedMessageId = pinnedMessageIds.get(0) + 1; + forceScrollToFirst = true; + } else { + forceNextPinnedMessageId = currentPinnedMessageId - 1; + forceScrollToFirst = false; + } + updateMessagesVisiblePart(false); + } } }); @@ -4221,23 +4517,76 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selector.setBackground(Theme.getSelectorDrawable(false)); pinnedMessageView.addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 2)); - pinnedLineView = new View(context); - pinnedLineView.setBackgroundColor(Theme.getColor(Theme.key_chat_topPanelLine)); - pinnedMessageView.addView(pinnedLineView, LayoutHelper.createFrame(2, 32, Gravity.LEFT | Gravity.TOP, 8, 8, 0, 0)); + pinnedLineView = new PinnedLineView(context); + pinnedMessageView.addView(pinnedLineView, LayoutHelper.createFrame(2, 48, Gravity.LEFT | Gravity.TOP, 8, 0, 0, 0)); - pinnedMessageImageView = new BackupImageView(context); - pinnedMessageView.addView(pinnedMessageImageView, LayoutHelper.createFrame(32, 32, Gravity.TOP | Gravity.LEFT, 17, 8, 0, 0)); + pinnedCounterTextView = new NumberTextView(context); + pinnedCounterTextView.setAddNumber(); + pinnedCounterTextView.setTextSize(14); + pinnedCounterTextView.setTextColor(Theme.getColor(Theme.key_chat_topPanelTitle)); + pinnedCounterTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + pinnedMessageView.addView(pinnedCounterTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7, 44, 0)); - pinnedMessageNameTextView = new SimpleTextView(context); - pinnedMessageNameTextView.setTextSize(14); - pinnedMessageNameTextView.setTextColor(Theme.getColor(Theme.key_chat_topPanelTitle)); - pinnedMessageNameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - pinnedMessageView.addView(pinnedMessageNameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, AndroidUtilities.dp(18), Gravity.TOP | Gravity.LEFT, 18, 7.3f, 40, 0)); + for (int a = 0; a < 2; a++) { + pinnedNameTextView[a] = new SimpleTextView(context) { + @Override + protected boolean createLayout(int width) { + boolean result = super.createLayout(width); + if (this == pinnedNameTextView[0] && pinnedCounterTextView != null) { + int newX = getTextWidth() + AndroidUtilities.dp(4); + if (newX != pinnedCounterTextViewX) { + pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX = newX); + } + } + return result; + } + }; + pinnedNameTextView[a].setTextSize(14); + pinnedNameTextView[a].setTextColor(Theme.getColor(Theme.key_chat_topPanelTitle)); + pinnedNameTextView[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + pinnedMessageView.addView(pinnedNameTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7.3f, 44, 0)); - pinnedMessageTextView = new SimpleTextView(context); - pinnedMessageTextView.setTextSize(14); - pinnedMessageTextView.setTextColor(Theme.getColor(Theme.key_chat_topPanelMessage)); - pinnedMessageView.addView(pinnedMessageTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, AndroidUtilities.dp(18), Gravity.TOP | Gravity.LEFT, 18, 25.3f, 40, 0)); + pinnedMessageTextView[a] = new SimpleTextView(context) { + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + if (this == pinnedMessageTextView[0] && pinnedNextAnimation[1] != null) { + if (forceScrollToFirst && translationY < 0) { + pinnedLineView.setTranslationY(translationY / 2); + } else { + pinnedLineView.setTranslationY(0); + } + } + } + }; + pinnedMessageTextView[a].setTextSize(14); + pinnedMessageTextView[a].setTextColor(Theme.getColor(Theme.key_chat_topPanelMessage)); + pinnedMessageView.addView(pinnedMessageTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 25.3f, 44, 0)); + + pinnedMessageImageView[a] = new BackupImageView(context); + pinnedMessageImageView[a].setRoundRadius(AndroidUtilities.dp(2)); + pinnedMessageView.addView(pinnedMessageImageView[a], LayoutHelper.createFrame(32, 32, Gravity.TOP | Gravity.LEFT, 17, 8, 0, 0)); + if (a == 1) { + pinnedMessageTextView[a].setVisibility(View.INVISIBLE); + pinnedNameTextView[a].setVisibility(View.INVISIBLE); + pinnedMessageImageView[a].setVisibility(View.INVISIBLE); + } + } + + pinnedListButton = new ImageView(context); + pinnedListButton.setImageResource(R.drawable.menu_pinnedlist); + pinnedListButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); + pinnedListButton.setScaleType(ImageView.ScaleType.CENTER); + pinnedListButton.setContentDescription(LocaleController.getString("AccPinnedMessagesList", R.string.AccPinnedMessagesList)); + pinnedListButton.setVisibility(View.INVISIBLE); + pinnedListButton.setAlpha(0.0f); + pinnedListButton.setScaleX(0.4f); + pinnedListButton.setScaleY(0.4f); + if (Build.VERSION.SDK_INT >= 21) { + pinnedListButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_inappPlayerClose) & 0x19ffffff)); + } + pinnedMessageView.addView(pinnedListButton, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 7, 0)); + pinnedListButton.setOnClickListener(v -> openPinnedMessagesList(false)); closePinned = new ImageView(context); closePinned.setImageResource(R.drawable.miniplayer_close); @@ -4250,7 +4599,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (Build.VERSION.SDK_INT >= 21) { closePinned.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14))); } - pinnedMessageView.addView(closePinned, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP)); + pinnedMessageView.addView(closePinned, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); closePinned.setOnClickListener(v -> { if (getParentActivity() == null) { return; @@ -4271,16 +4620,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("UnpinMessageAlertTitle", R.string.UnpinMessageAlertTitle)); builder.setMessage(LocaleController.getString("UnpinMessageAlert", R.string.UnpinMessageAlert)); - builder.setPositiveButton(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), (dialogInterface, i) -> getMessagesController().pinMessage(currentChat, currentUser, 0, false)); + builder.setPositiveButton(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), (dialogInterface, i) -> { + MessageObject messageObject = pinnedMessageObjects.get(currentPinnedMessageId); + if (messageObject == null) { + messageObject = messagesDict[0].get(currentPinnedMessageId); + } + unpinMessage(messageObject); + }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); - } else { + } else if (!pinnedMessageIds.isEmpty()) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - if (chatInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).commit(); - } else if (userInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); - } + preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); updatePinnedMessageView(true); } }); @@ -4403,7 +4754,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } closeReportSpam.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closeReportSpam.setScaleType(ImageView.ScaleType.CENTER); - topChatPanelView.addView(closeReportSpam, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP)); + topChatPanelView.addView(closeReportSpam, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); closeReportSpam.setOnClickListener(v -> { long did = dialog_id; if (currentEncryptedChat != null) { @@ -4450,6 +4801,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollToMessageId(returnToMessageId, 0, true, returnToLoadIndex, true); } else { scrollToLastMessage(); + if (!pinnedMessageIds.isEmpty()) { + forceScrollToFirst = true; + forceNextPinnedMessageId = pinnedMessageIds.get(0); + } } }); @@ -4893,7 +5248,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } })); - if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { + if (!ChatObject.isChannel(currentChat) || currentChat.megagroup) { mentionsAdapter.setBotInfo(botInfo); } mentionsAdapter.setParentFragment(this); @@ -4908,25 +5263,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Object object = mentionsAdapter.getItem(position); int start = mentionsAdapter.getResultStartPosition(); int len = mentionsAdapter.getResultLength(); - if (object instanceof TLRPC.User) { + if (object instanceof TLRPC.Chat) { if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { - searchUserMessages((TLRPC.User) object); + searchUserMessages(null, (TLRPC.Chat) object); + } + } else if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; + if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { + searchUserMessages(user, null); } else { - TLRPC.User user = (TLRPC.User) object; - if (user != null) { - if (user.username != null) { - chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); - } else { - String name = UserObject.getFirstName(user, false); - Spannable spannable = new SpannableString(name + " "); - spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - chatActivityEnterView.replaceWithText(start, len, spannable, false); - } + if (user.username != null) { + chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); + } else { + String name = UserObject.getFirstName(user, false); + Spannable spannable = new SpannableString(name + " "); + spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + chatActivityEnterView.replaceWithText(start, len, spannable, false); } } } else if (object instanceof String) { if (mentionsAdapter.isBotCommands()) { - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, notify, scheduleDate); chatActivityEnterView.setFieldText(""); @@ -4944,7 +5301,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.replaceWithText(start, len, object + " ", false); } } else if (object instanceof TLRPC.BotInlineResult) { - if (chatActivityEnterView.getFieldText() == null || !inScheduleMode && checkSlowMode(view)) { + if (chatActivityEnterView.getFieldText() == null || chatMode != MODE_SCHEDULED && checkSlowMode(view)) { return; } TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) object; @@ -4955,7 +5312,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not PhotoViewer.getInstance().setParentActivity(getParentActivity()); PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionsAdapter.getItemPosition(position), 3, false, botContextProvider, ChatActivity.this); } else { - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> sendBotInlineResult(result, notify, scheduleDate)); } else { sendBotInlineResult(result, true, 0); @@ -5095,8 +5452,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentiondownButton.setContentDescription(LocaleController.getString("AccDescrMentionDown", R.string.AccDescrMentionDown)); if (!AndroidUtilities.isTablet() || AndroidUtilities.isSmallTablet()) { - contentView.addView(fragmentLocationContextView = new FragmentContextView(context, this, true), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); - contentView.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + contentView.addView(fragmentLocationContextView = new FragmentContextView(context, this, true), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + contentView.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); fragmentContextView.setAdditionalContextView(fragmentLocationContextView); fragmentLocationContextView.setAdditionalContextView(fragmentContextView); } @@ -5196,9 +5553,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - + public void checkAnimation() { if (actionBar.isActionModeShowed()) { if (messageEditTextAnimator != null) { messageEditTextAnimator.cancel(); @@ -5226,7 +5581,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topLineView.setTranslationY(animatedTop); } } - contentView.setClipChildren(false); changeBoundAnimator = ValueAnimator.ofFloat(1f, 0); changeBoundAnimator.addUpdateListener(a -> { @@ -5249,8 +5603,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatListView.setTranslationY(v); invalidateChatListViewTopPadding(); - updateChatListViewTopPadding(); - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); } invalidate(); }); @@ -5266,7 +5619,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { chatListView.setTranslationY(0); } - contentView.setClipChildren(true); changeBoundAnimator = null; } }); @@ -5279,7 +5631,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not changeBoundAnimator.start(); } invalidateChatListViewTopPadding(); - updateMessagesVisiblePart(true); + invalidateMessagesVisiblePart(); chatActivityEnterViewAnimateFromTop = 0; } else if (lastContentViewHeight != contentView.getMeasuredHeight()) { chatActivityEnterViewAnimateFromTop = 0; @@ -5308,15 +5660,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onLineCountChanged(int oldLineCount, int newLineCount) { if (chatActivityEnterView != null) { - if (!TextUtils.isEmpty(messageEditText.getText())) { - shouldAnimateEditTextWithBounds = true; - messageEditTextPredrawHeigth = messageEditText.getMeasuredHeight(); - messageEditTextPredrawScrollY = messageEditText.getScrollY(); - } else { - messageEditText.animate().cancel(); - messageEditText.setOffsetY(0); - shouldAnimateEditTextWithBounds = false; - } + shouldAnimateEditTextWithBounds = true; + messageEditTextPredrawHeigth = messageEditText.getMeasuredHeight(); + messageEditTextPredrawScrollY = messageEditText.getScrollY(); contentView.invalidate(); chatActivityEnterViewAnimateFromTop = chatActivityEnterView.getBackgroundTop(); } @@ -5605,7 +5951,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean hasScheduledMessages() { - return scheduledMessagesCount > 0 && !inScheduleMode; + return scheduledMessagesCount > 0 && chatMode == 0; } @Override @@ -5627,6 +5973,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void bottomPanelTranslationYChanged(float translation) { + if (translation != 0) { + wasManualScroll = true; + } bottomPanelTranslationY = chatActivityEnterView.pannelAniamationInProgress() ? chatActivityEnterView.getEmojiPadding() - translation : 0; chatActivityEnterView.setTranslationY(translation); @@ -5640,7 +5989,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentiondownButton.setTranslationY(pagedownButton.getVisibility() != View.VISIBLE ? translation : translation - AndroidUtilities.dp(72)); } invalidateChatListViewTopPadding(); - updateChatListViewTopPadding(); + invalidateMessagesVisiblePart(); updateTextureViewPosition(false); contentView.invalidate(); } @@ -5649,6 +5998,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void prepareMessageSending() { waitingForSendingMessageLoad = true; } + + @Override + public void onTrendingStickersShowed(boolean show) { + if (show) { + AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); + fragmentView.requestLayout(); + } else { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + } }); chatActivityEnterView.setDialogId(dialog_id, currentAccount); if (chatInfo != null) { @@ -5683,11 +6042,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (pagedownButton != null) { pagedownButton.setTranslationY(translationY); + if (mentiondownButton != null) { + mentiondownButton.setTranslationY(pagedownButton.getVisibility() != VISIBLE ? translationY : translationY - AndroidUtilities.dp(72)); + } } - if (mentiondownButton != null) { - mentiondownButton.setTranslationY(pagedownButton.getVisibility() != VISIBLE ? translationY : translationY - AndroidUtilities.dp(72)); - } - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); if (fragmentView != null) { fragmentView.invalidate(); } @@ -5791,6 +6150,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyLayout.addView(replyObjectTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 52, 24, 52, 0)); replyImageView = new BackupImageView(context); + replyImageView.setRoundRadius(AndroidUtilities.dp(2)); replyLayout.addView(replyImageView, LayoutHelper.createFrame(34, 34, Gravity.TOP | Gravity.LEFT, 52, 6, 0, 0)); stickersPanel = new FrameLayout(context); @@ -5815,7 +6175,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean isInScheduleMode() { - return inScheduleMode; + return chatMode == MODE_SCHEDULED; } @Override @@ -5918,7 +6278,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView.isFastScrollAnimationRunning()) { return; } - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages); + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) { showSearchAsListHint(); @@ -5938,7 +6298,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView.isFastScrollAnimationRunning()) { return; } - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages); + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); }); searchDownButton.setContentDescription(LocaleController.getString("AccDescrSearchPrev", R.string.AccDescrSearchPrev)); @@ -5957,6 +6317,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUserButton.setVisibility(View.GONE); searchingForUser = true; searchingUserMessages = null; + searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString("SearchMembers", R.string.SearchMembers)); searchItem.setSearchFieldCaption(LocaleController.getString("SearchFrom", R.string.SearchFrom)); AndroidUtilities.showKeyboard(searchItem.getSearchField()); @@ -6042,7 +6403,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - if (currentUser != null && userBlocked) { + if (chatMode == MODE_PINNED) { + finishFragment(); + chatActivityDelegate.onUnpin(true, bottomOverlayChatText.getTag() == null); + } else if (currentUser != null && userBlocked) { if (currentUser.bot) { String botUserLast = botUser; botUser = null; @@ -6185,7 +6549,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateDistanceView(false); chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); - chatScrollHelper.setScrollListener(() -> updateMessagesVisiblePart(false)); + chatScrollHelper.setScrollListener(this::invalidateMessagesVisiblePart); chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); try { @@ -6231,12 +6595,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); textSelectionHelper.setParentView(chatListView); - if (getArguments().containsKey("search_from_user_id")) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(getArguments().getInt("search_from_user_id")); + int searchFromUserId = getArguments().getInt("search_from_user_id", 0); + int searchFromChatId = getArguments().getInt("search_from_chat_id", 0); + if (searchFromUserId != 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(searchFromUserId); if (user != null) { openSearchWithText(""); searchUserButton.callOnClick(); - searchUserMessages(user); + searchUserMessages(user, null); + } + } else if (searchFromChatId != 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(searchFromChatId); + if (chat != null) { + openSearchWithText(""); + searchUserButton.callOnClick(); + searchUserMessages(null, chat); } } if (replyingMessageObject != null) { @@ -6245,14 +6618,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return fragmentView; } - private void searchUserMessages(TLRPC.User user) { + private void searchUserMessages(TLRPC.User user, TLRPC.Chat chat) { searchingUserMessages = user; - if (searchingUserMessages == null) { + searchingChatMessages = chat; + if (searchingUserMessages == null && searchingChatMessages == null) { return; } - String name = searchingUserMessages.first_name; - if (TextUtils.isEmpty(name)) { - name = searchingUserMessages.last_name; + String name; + if (searchingUserMessages != null) { + name = searchingUserMessages.first_name; + if (TextUtils.isEmpty(name)) { + name = searchingUserMessages.last_name; + } + } else { + name = searchingChatMessages.title; + } + if (name.length() > 10) { + name = name.substring(0, 10); } searchingForUser = false; String from = LocaleController.getString("SearchFrom", R.string.SearchFrom); @@ -6262,7 +6644,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false); searchItem.setSearchFieldHint(null); searchItem.clearSearchText(); - getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages); + getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } Animator distanceViewAnimator; @@ -6309,6 +6691,133 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private void openPinnedMessagesList(boolean preview) { + if (getParentActivity() == null || parentLayout == null || parentLayout.getLastFragment() != this || pinnedMessageIds.isEmpty()) { + return; + } + Bundle bundle = new Bundle(); + if (currentChat != null) { + bundle.putInt("chat_id", currentChat.id); + } else { + bundle.putInt("user_id", currentUser.id); + } + bundle.putInt("chatMode", MODE_PINNED); + ChatActivity fragment = new ChatActivity(bundle); + fragment.pinnedMessageIds = new ArrayList<>(pinnedMessageIds); + fragment.pinnedMessageObjects = new HashMap<>(pinnedMessageObjects); + for (int a = 0, N = pinnedMessageIds.size(); a < N; a++) { + Integer id = pinnedMessageIds.get(a); + MessageObject object = pinnedMessageObjects.get(id); + MessageObject object2 = messagesDict[0].get(id); + if (object == null) { + object = object2; + } else if (object2 != null) { + object.mediaExists = object2.mediaExists; + object.attachPathExists = object2.attachPathExists; + } + if (object != null) { + fragment.pinnedMessageObjects.put(id, object); + } + } + fragment.loadedPinnedMessagesCount = loadedPinnedMessagesCount; + fragment.totalPinnedMessagesCount = totalPinnedMessagesCount; + fragment.pinnedEndReached = pinnedEndReached; + fragment.userInfo = userInfo; + fragment.chatInfo = chatInfo; + fragment.chatActivityDelegate = new ChatActivityDelegate() { + @Override + public void openReplyMessage(int mid) { + scrollToMessageId(mid, 0, true, 0, true); + } + + @Override + public void openSearch(String text) { + openSearchWithText(text); + } + + @Override + public void onUnpin(boolean all, boolean hide) { + if (all) { + ArrayList ids = new ArrayList<>(pinnedMessageIds); + ArrayList objects = new ArrayList<>(pinnedMessageObjects.values()); + if (hide) { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); + updatePinnedMessageView(true); + } else { + getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, false, null, null, 0, 0, true); + } + showPinBulletin = true; + int tag = ++pinBullerinTag; + int oldTotalPinnedCount = getPinnedMessagesCount(); + pinBulletin = BulletinFactory.createUnpinAllMessagesBulletin(ChatActivity.this, oldTotalPinnedCount, hide, + () -> { + if (hide) { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + preferences.edit().remove("pin_" + dialog_id).commit(); + updatePinnedMessageView(true); + } else { + getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, true, objects, null, 0, oldTotalPinnedCount, pinnedEndReached); + } + if (tag == pinBullerinTag) { + pinBulletin = null; + } + }, + () -> { + if (!hide) { + getMessagesController().unpinAllMessages(currentChat, currentUser); + } + if (tag == pinBullerinTag) { + pinBulletin = null; + } + }); + } else { + MessageObject messageObject = pinnedMessageObjects.get(currentPinnedMessageId); + if (messageObject == null) { + messageObject = messagesDict[0].get(currentPinnedMessageId); + } + unpinMessage(messageObject); + } + } + }; + if (preview) { + int w = (int) (fragmentView.getMeasuredWidth() / 6.0f); + int h = (int) (fragmentView.getMeasuredHeight() / 6.0f); + Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.scale(1.0f / 6.0f, 1.0f / 6.0f); + fragmentView.draw(canvas); + Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(w, h) / 180)); + + if (blurredView == null) { + blurredView = new View(getParentActivity()); + contentView.addView(blurredView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } else { + int idx = contentView.indexOfChild(blurredView); + if (idx != contentView.getChildCount() - 1) { + contentView.removeView(blurredView); + contentView.addView(blurredView); + } + blurredView.setVisibility(View.VISIBLE); + } + + blurredView.setBackground(new BitmapDrawable(bitmap)); + blurredView.setAlpha(0.0f); + + presentFragmentAsPreview(fragment); + } else { + presentFragment(fragment, false); + } + } + + @Override + protected int getPreviewHeight() { + if (chatMode == MODE_PINNED && messages.size() == 2) { + return getHeightForMessage(messages.get(0)) + AndroidUtilities.dp(80) + ActionBar.getCurrentActionBarHeight(); + } + return super.getPreviewHeight(); + } + boolean animateTo; private void showProgressView(boolean show) { @@ -6386,7 +6895,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateChatListViewTopPadding() { - if (!invalidateChatListViewTopPadding) { + if (!invalidateChatListViewTopPadding || chatListView == null) { return; } float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); @@ -6394,22 +6903,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } - - int p = (int) (AndroidUtilities.dp(4) + contentPaddingTop + distanceTopViewOffset + topPanelViewH + pinnedViewH); - if (chatListView != null && chatLayoutManager != null && chatAdapter != null && chatLayoutManager.findLastVisibleItemPosition() == chatAdapter.getItemCount() - 1) { - p += contentPanTranslation + bottomPanelTranslationY; - if (bottomPanelTranslationY == 0 && contentPanTranslation == 0) { - p += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); - } - if (!inPreviewMode && chatActivityEnterView != null) { - p += chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51) - chatActivityEnterView.getAnimatedTop(); - } - } else { - p += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); - if (!inPreviewMode && chatActivityEnterView != null) { - p += chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51); - } + int oldPadding = chatListViewPaddingTop; + chatListViewPaddingTop = (int) (AndroidUtilities.dp(4) + contentPaddingTop + distanceTopViewOffset + topPanelViewH + pinnedViewH); + chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; + if (bottomPanelTranslationY == 0 && !chatActivityEnterView.pannelAniamationInProgress() && contentView.getLayoutParams().height < 0) { + chatListViewPaddingTop += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); } + if (!inPreviewMode && chatActivityEnterView != null) { + chatListViewPaddingTop += chatActivityEnterView.getHeightWithTopView() - AndroidUtilities.dp(51) - chatActivityEnterView.getAnimatedTop(); + } + + int p = chatListView.getMeasuredHeight() * 2 / 3; if (chatListView != null && chatLayoutManager != null && chatAdapter != null) { if (chatListView.getPaddingTop() != p) { @@ -6433,7 +6937,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3)); - chatListView.setTopGlowOffset(contentPaddingTop + chatListViewPaddingTop); if (firstVisPos != RecyclerView.NO_POSITION && scrollToMessageObject != null) { chatAdapter.updateRowsSafe(); @@ -6443,7 +6946,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); + } + + chatListView.setTopGlowOffset(chatListViewPaddingTop - AndroidUtilities.dp(4)); + + if (oldPadding != chatListViewPaddingTop) { + int n = chatListView.getChildCount(); + for (int i = 0; i < n; i++) { + View child = chatListView.getChildAt(i); + int adapterPosition = chatListView.getChildAdapterPosition(child); + if (adapterPosition == chatAdapter.getItemCount() - 1) { + if (child.getTop() > chatListViewPaddingTop) { + chatListView.scrollBy(0, child.getTop() - chatListViewPaddingTop); + } + break; + } + } + } + + if (!isThreadChat() && !wasManualScroll && unreadMessageObject != null && chatListView != null) { + chatListView.scrollBy(0, oldPadding - chatListViewPaddingTop); } } @@ -6453,6 +6976,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void invalidateChatListViewTopPadding() { invalidateChatListViewTopPadding = true; contentView.invalidate(); + chatListView.invalidate(); float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); float pinnedViewH = 0; @@ -6821,7 +7345,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForLoad.add(lastLoadIndex); postponedScrollMessageId = 0; postponedScrollIsCanceled = false; - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); floatingDateView.setAlpha(0.0f); floatingDateView.setTag(null); } @@ -6878,11 +7402,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null || chatAttachAlert == null) { return; } - if (chatAttachAlert != null) { - editingMessageObject = chatAttachAlert.getEditingMessageObject(); - } else { - editingMessageObject = null; - } + editingMessageObject = chatAttachAlert.getEditingMessageObject(); if (button == 8 || button == 7 || button == 4 && !chatAttachAlert.getPhotoLayout().getSelectedPhotos().isEmpty()) { if (button != 8) { chatAttachAlert.dismiss(); @@ -6962,16 +7482,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void doOnIdle(Runnable runnable) { - if (chatListItemAniamtor != null && chatListItemAniamtor.isRunning()) { - chatListItemAniamtor.runOnAnimationEnd(runnable); - } else { - runnable.run(); - } + ChatActivity.this.doOnIdle(runnable); } }); } } + public void doOnIdle(Runnable runnable) { + NotificationCenter.getInstance(currentAccount).doOnIdle(runnable); + } + public long getDialogId() { return dialog_id; } @@ -6999,7 +7519,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void afterMessageSend() { hideFieldPanel(false); - if (!inScheduleMode) { + if (chatMode == 0) { getMediaDataController().cleanDraft(dialog_id, threadMessageId, true); } } @@ -7080,7 +7600,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { bundle.putInt("user_id", currentUser.id); } - bundle.putBoolean("scheduled", true); + bundle.putInt("chatMode", MODE_SCHEDULED); ChatActivity fragment = new ChatActivity(bundle); fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override @@ -7165,11 +7685,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Object item = stickersAdapter.getItem(position); Object parent = stickersAdapter.getItemParent(position); if (item instanceof TLRPC.TL_document) { - if (!inScheduleMode && checkSlowMode(view)) { + if (chatMode == 0 && checkSlowMode(view)) { return; } TLRPC.TL_document document = (TLRPC.TL_document) item; - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, getThreadMessage(), parent, notify, scheduleDate)); } else { getSendMessagesHelper().sendSticker(document, dialog_id, replyingMessageObject, getThreadMessage(), parent, true, 0); @@ -7211,7 +7731,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } else { SendMessagesHelper.getInstance(currentAccount).sendMessage(getUserConfig().getCurrentUser(), dialog_id, messageObject, getThreadMessage(), null, null, true, 0); - if (!inScheduleMode) { + if (chatMode == 0) { moveScrollToLastMessage(); } hideFieldPanel(false); @@ -7254,7 +7774,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void showVoiceHint(boolean hide, boolean video) { - if (getParentActivity() == null || fragmentView == null || hide && voiceHintTextView == null || inScheduleMode) { + if (getParentActivity() == null || fragmentView == null || hide && voiceHintTextView == null || chatMode != 0) { return; } if (voiceHintTextView == null) { @@ -7386,7 +7906,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void showScheduledOrNoSoundHint() { - boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && !isInScheduleMode()); + boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); if (SharedConfig.scheduledOrNoSoundHintShows >= 3 || System.currentTimeMillis() % 4 != 0 || disableNoSound) { return; } @@ -7850,7 +8370,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not floatingDateAnimation.start(); } if (!scroll) { - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); hideDateDelay = 1000; } } @@ -7902,8 +8422,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public boolean isKeyboardVisible() { - int keyboardSize = SharedConfig.smoothKeyboard ? 0 : contentView.getKeyboardHeight(); - return keyboardSize > AndroidUtilities.dp(20); + return contentView.getKeyboardHeight() > AndroidUtilities.dp(20); } private void checkScrollForLoad(boolean scroll) { @@ -7924,24 +8443,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not loading = true; waitingForLoad.add(lastLoadIndex); if (messagesByDays.size() != 0) { - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, maxMessageId[0], 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, maxMessageId[0], 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } else if (mergeDialogId != 0 && !endReached[1]) { loading = true; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(mergeDialogId, 0, false, 50, maxMessageId[1], 0, !cacheEndReached[1], minDate[1], classGuid, 0, 0, false, inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(mergeDialogId, 0, false, 50, maxMessageId[1], 0, !cacheEndReached[1], minDate[1], classGuid, 0, 0, false, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } if (visibleItemCount > 0 && !loadingForward && firstVisibleItem <= 10) { if (mergeDialogId != 0 && !forwardEndReached[1]) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(mergeDialogId, 0, false, 50, minMessageId[1], 0, true, maxDate[1], classGuid, 1, 0, false, inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(mergeDialogId, 0, false, 50, minMessageId[1], 0, true, maxDate[1], classGuid, 1, 0, false, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loadingForward = true; } else if (!forwardEndReached[0]) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, minMessageId[0], 0, true, maxDate[0], classGuid, 1, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, minMessageId[0], 0, true, maxDate[0], classGuid, 1, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loadingForward = true; } } @@ -8300,7 +8819,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (arrayList == null || arrayList.isEmpty()) { return; } - if ((scheduleDate != 0) == inScheduleMode) { + if ((scheduleDate != 0) == (chatMode == MODE_SCHEDULED)) { waitingForSendingMessageLoad = true; } if (!fromMyName) { @@ -8804,6 +9323,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView.isFastScrollAnimationRunning()) { return; } + forceNextPinnedMessageId = 0; + forceScrollToFirst = false; chatScrollHelper.setScrollDirection(RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN); if (forwardEndReached[0] && first_unread_id == 0 && startLoadFromMessageId == 0) { if (chatLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) { @@ -8830,7 +9351,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForLoad.clear(); waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, true, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, true, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } @@ -8848,7 +9369,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (videoPlayerContainer != null && (messageObject.isRoundVideo() || messageObject.isVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); - videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + messageCell.getY() + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); + videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + messageCell.getY() + imageReceiver.getImageY() + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoPlayerContainer.getLayoutParams(); if (messageObject.isRoundVideo()) { videoPlayerContainer.setTag(R.id.parent_tag, null); @@ -8907,6 +9428,62 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + public void invalidateMessagesVisiblePart() { + invalidateMessagesVisiblePart = true; + if (fragmentView != null) { + fragmentView.invalidate(); + } + } + + private Integer findClosest(ArrayList arrayList, int target, int[] index) { + if (arrayList.isEmpty()) { + return 0; + } + Integer val = arrayList.get(0); + if (target >= val) { + index[0] = 0; + return val; + } + int n = arrayList.size(); + val = arrayList.get(n - 1); + if (target <= val) { + index[0] = n - 1; + return val; + } + + int i = 0, j = n, mid = 0; + while (i < j) { + mid = (i + j) / 2; + + val = arrayList.get(mid); + if (val == target) { + index[0] = mid; + return val; + } + if (target < val) { + if (mid > 0) { + Integer val2 = arrayList.get(mid - 1); + if (target > val2) { + index[0] = mid - 1; + return val2; + } + } + i = mid + 1; + } else { + if (mid > 0) { + Integer val2 = arrayList.get(mid - 1); + if (target < val2) { + index[0] = mid; + return val; + } + } + j = mid; + } + } + index[0] = mid; + return arrayList.get(mid); + } + public void updateMessagesVisiblePart(boolean inLayout) { if (chatListView == null) { return; @@ -8919,8 +9496,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View minChild = null; View minMessageChild = null; boolean foundTextureViewMessage = false; - boolean previousPinnedMessageVisible = replyMessageVisible; - replyMessageVisible = firstLoading; + boolean previousThreadMessageVisible = threadMessageVisible; + int previousPinnedMessageId = currentPinnedMessageId; + int maxVisibleId = Integer.MIN_VALUE; + threadMessageVisible = firstLoading; Integer currentReadMaxId; long threadId = threadMessageId; @@ -8936,27 +9515,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int maxPositiveUnreadId = Integer.MIN_VALUE; int maxNegativeUnreadId = Integer.MAX_VALUE; int maxUnreadDate = Integer.MIN_VALUE; - int lastVisibleId = currentEncryptedChat != null ? Integer.MAX_VALUE : Integer.MIN_VALUE; int recyclerChatViewHeight = (contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop()); if (contentView.getKeyboardHeight() == 0) { recyclerChatViewHeight -= chatActivityEnterView.getEmojiPadding(); } pollsToCheck.clear(); - float animatedTop = 0; - if (chatActivityEnterView != null && chatLayoutManager.findLastVisibleItemPosition() != chatAdapter.getItemCount() - 1) { - animatedTop = -chatActivityEnterView.getAnimatedTop(); - } + float cilpTop = chatListViewPaddingTop; for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); MessageObject messageObject = null; int top = (int) view.getY(); int bottom = top + view.getMeasuredHeight(); - if (bottom < 0 || top > chatListView.getMeasuredHeight()) { + if (bottom <= cilpTop || top > chatListView.getMeasuredHeight()) { continue; } if (view instanceof ChatMessageCell) { ChatMessageCell messageCell = (ChatMessageCell) view; + messageObject = messageCell.getMessageObject(); + maxVisibleId = Math.max(maxVisibleId, messageObject.getId()); int viewTop = top >= 0 ? 0 : -top; int viewBottom = messageCell.getMeasuredHeight(); @@ -8965,18 +9542,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } messageCell.setVisiblePart(viewTop, viewBottom - viewTop, recyclerChatViewHeight, contentView.getKeyboardHeight()); - messageObject = messageCell.getMessageObject(); - if (!replyMessageVisible && threadMessageObject != null && messageObject == threadMessageObject && messageCell.getBottom() > chatListView.getPaddingTop()) { - replyMessageVisible = true; + if (!threadMessageVisible && threadMessageObject != null && messageObject == threadMessageObject && messageCell.getBottom() > chatListViewPaddingTop) { + threadMessageVisible = true; } - boolean isVideo; - if (videoPlayerContainer != null && (isVideo = messageObject.isVideo() || messageObject.isRoundVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { + if (videoPlayerContainer != null && (messageObject.isVideo() || messageObject.isRoundVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); - if (isVideo && top + imageReceiver.getImageY2() < 0) { + if (top + imageReceiver.getImageY2() < 0) { foundTextureViewMessage = false; } else { videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); - videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + top + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); + videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + top + imageReceiver.getImageY() + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); fragmentView.invalidate(); videoPlayerContainer.invalidate(); foundTextureViewMessage = true; @@ -8984,10 +9559,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (view instanceof ChatActionCell) { messageObject = ((ChatActionCell) view).getMessageObject(); + if (messageObject != null) { + maxVisibleId = Math.max(maxVisibleId, messageObject.getId()); + } } else if (view instanceof BotHelpCell) { view.invalidate(); } - if (!inScheduleMode && messageObject != null) { + if (chatMode != MODE_SCHEDULED && messageObject != null) { int id = messageObject.getId(); if (!isThreadChat() && (!messageObject.isOut() && messageObject.isUnread() || messageObject.messageOwner.from_scheduled && id > currentReadMaxId) || id > 0 && isThreadChat() && id > currentReadMaxId && id > replyMaxReadId) { if (id > 0) { @@ -9002,12 +9580,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pollsToCheck.add(messageObject); } } - if (view.getBottom() <= chatListView.getPaddingTop() + AndroidUtilities.dp(1) + animatedTop) { - if (view instanceof ChatActionCell && messageObject.isDateObject) { - view.setAlpha(0f); - } - continue; - } int position = view.getBottom(); if (position < minPositionHolder) { minPositionHolder = position; @@ -9028,6 +9600,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + currentPinnedMessageId = 0; + if (maxVisibleId == Integer.MIN_VALUE) { + if (startLoadFromMessageId != 0) { + maxVisibleId = startLoadFromMessageId; + } else if (!pinnedMessageIds.isEmpty()) { + maxVisibleId = pinnedMessageIds.get(0) + 1; + } + } + if (!pinnedMessageIds.isEmpty()) { + currentPinnedMessageId = findClosest(pinnedMessageIds, forceNextPinnedMessageId != 0 && (maxVisibleId > forceNextPinnedMessageId || forceScrollToFirst || chatListView.isFastScrollAnimationRunning()) ? forceNextPinnedMessageId : maxVisibleId, currentPinnedMessageIndex); + if (!loadingPinnedMessagesList && !pinnedEndReached && !pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2) { + getMediaDataController().loadPinnedMessages(dialog_id, pinnedMessageIds.get(pinnedMessageIds.size() - 1), 0); + loadingPinnedMessagesList = true; + } + } getMessagesController().addToPollsQueue(dialog_id, pollsToCheck); if (videoPlayerContainer != null) { if (!foundTextureViewMessage) { @@ -9047,27 +9634,64 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MediaController.getInstance().setCurrentVideoVisible(true); } } - if (minMessageChild != null && (chatListItemAniamtor == null || !chatListItemAniamtor.isRunning())) { + if (minMessageChild != null) { MessageObject messageObject; if (minMessageChild instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) minMessageChild).getMessageObject(); } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } - floatingDateView.setCustomDate(messageObject.messageOwner.date, inScheduleMode, true); + floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); if (minDateChild != null) { - if (minDateChild.getTop() > chatListView.getPaddingTop() + animatedTop || currentFloatingTopIsNotMessage) { + boolean showFloatingView = false; + if (minDateChild.getY() > cilpTop || currentFloatingTopIsNotMessage) { if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } - hideFloatingDateView(!currentFloatingTopIsNotMessage); + if (chatListView.getChildAdapterPosition(minDateChild) == chatAdapter.messagesStartRow + messages.size() - 1) { + showFloatingView = false; + if (minDateChild.getAlpha() != 1.0f) { + minDateChild.setAlpha(1.0f); + } + if (floatingDateAnimation != null) { + floatingDateAnimation.cancel(); + floatingDateAnimation = null; + } + floatingDateView.setTag(null); + floatingDateView.setAlpha(0); + currentFloatingDateOnScreen = false; + } else { + hideFloatingDateView(!currentFloatingTopIsNotMessage); + } } else { if (minDateChild.getAlpha() != 0.0f) { minDateChild.setAlpha(0.0f); } + showFloatingView = true; + } + float offset = minDateChild.getY() + minDateChild.getMeasuredHeight() - cilpTop; + if (offset > floatingDateView.getMeasuredHeight() && offset < floatingDateView.getMeasuredHeight() * 2) { + if (chatListView.getChildAdapterPosition(minDateChild) == chatAdapter.messagesStartRow + messages.size() - 1) { + showFloatingView = false; + if (minDateChild.getAlpha() != 1.0f) { + minDateChild.setAlpha(1.0f); + } + if (floatingDateAnimation != null) { + floatingDateAnimation.cancel(); + floatingDateAnimation = null; + } + floatingDateView.setTag(null); + floatingDateView.setAlpha(0); + } else { + floatingDateViewOffset = -floatingDateView.getMeasuredHeight() * 2 + offset; + } + } else { + floatingDateViewOffset = 0; + } + if (showFloatingView) { if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); floatingDateAnimation = null; @@ -9080,21 +9704,57 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } currentFloatingDateOnScreen = true; } - float offset = minDateChild.getBottom() - chatListView.getPaddingTop() - animatedTop; - if (offset > floatingDateView.getMeasuredHeight() && offset < floatingDateView.getMeasuredHeight() * 2) { - floatingDateViewOffset = -floatingDateView.getMeasuredHeight() * 2 + offset; - } else { - floatingDateViewOffset = 0; - } } else { hideFloatingDateView(true); floatingDateViewOffset = 0; } - if (isThreadChat() && previousPinnedMessageVisible != replyMessageVisible) { - updatePinnedMessageView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); + if (isThreadChat()) { + if (previousThreadMessageVisible != threadMessageVisible) { + updatePinnedMessageView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); + } + } else { + if (currentPinnedMessageId != 0) { + MessageObject object = pinnedMessageObjects.get(currentPinnedMessageId); + if (object == null) { + object = messagesDict[0].get(currentPinnedMessageId); + } + if (object == null) { + if (loadingPinnedMessages.indexOfKey(currentPinnedMessageId) < 0) { + loadingPinnedMessages.put(currentPinnedMessageId, true); + ArrayList ids = new ArrayList<>(); + ids.add(currentPinnedMessageId); + getMediaDataController().loadPinnedMessages(dialog_id, ChatObject.isChannel(currentChat) ? currentChat.id : 0, ids, true); + } + currentPinnedMessageId = previousPinnedMessageId; + } + } else if (previousPinnedMessageId != 0 && !pinnedMessageIds.isEmpty()) { + currentPinnedMessageId = previousPinnedMessageId; + } + if (previousPinnedMessageId != currentPinnedMessageId) { + int animateToNext; + if (previousPinnedMessageId == 0) { + animateToNext = 0; + } else if (previousPinnedMessageId > currentPinnedMessageId) { + animateToNext = 1; + } else { + animateToNext = 2; + } + updatePinnedMessageView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150, animateToNext); + } else { + updatePinnedListButton(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); + } + } + if (floatingDateView != null) { + float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); + float pinnedViewH = 0; + if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); + } + int viewsOffset = (int) (contentPaddingTop + topPanelViewH + pinnedViewH); + floatingDateView.setTranslationY(contentPanTranslation + floatingDateViewOffset + viewsOffset + distanceTopViewOffset); } invalidateChatListViewTopPadding(); - if (!firstLoading && !paused && !inPreviewMode && !inScheduleMode && !getMessagesController().ignoreSetOnline) { + if (!firstLoading && !paused && !inPreviewMode && fragmentOpened && chatMode == 0 && !getMessagesController().ignoreSetOnline) { int scheduledRead = 0; if ((maxPositiveUnreadId != Integer.MIN_VALUE || maxNegativeUnreadId != Integer.MAX_VALUE)) { int counterDecrement = 0; @@ -9222,16 +9882,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private int getScrollOffsetForMessage(MessageObject object) { - int offset = Integer.MAX_VALUE; + int exactlyHeight = getHeightForMessage(object); + return Math.max(-AndroidUtilities.dp(2), (chatListView.getMeasuredHeight() - chatListViewPaddingTop - exactlyHeight) / 2); + } + private int getHeightForMessage(MessageObject object) { if (dummyMessageCell == null) { dummyMessageCell = new ChatMessageCell(getParentActivity()); } dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isBot = currentUser != null && currentUser.bot; dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; - int exactlyHeight = dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId())); - return Math.max(-AndroidUtilities.dp(2), offset == Integer.MAX_VALUE ? (chatListView.getMeasuredHeight() - chatListView.getPaddingTop() - exactlyHeight) / 2 : offset); + return dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId())); } private void startMessageUnselect() { @@ -9261,10 +9923,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } + forceNextPinnedMessageId = 0; + forceScrollToFirst = false; wasManualScroll = true; MessageObject object = messagesDict[loadIndex].get(id); boolean query = false; int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; + int scrollFromIndex = 0; if (fromMessageId != 0) { boolean scrollDown = fromMessageId < id; if (isSecretChat()) { @@ -9282,6 +9947,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.getId() == 0) { continue; } + scrollFromIndex = i - chatAdapter.messagesStartRow; boolean scrollDown = messageObject.getId() < id; if (isSecretChat()) { scrollDown = !scrollDown; @@ -9305,6 +9971,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int index = messages.indexOf(object); if (index != -1) { + if (scrollFromIndex > 0) { + scrollDirection = scrollFromIndex > index ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + chatScrollHelper.setScrollDirection(scrollDirection); + } removeSelectedMessageHighlight(); if (select) { highlightMessageId = id; @@ -9336,7 +10006,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (found) { int yOffset = getScrollOffsetForMessage(object); - int scrollY = view.getTop() - chatListView.getPaddingTop() - yOffset; + int scrollY = view.getTop() - chatListViewPaddingTop - yOffset; int maxScrollOffset = chatListView.computeVerticalScrollRange() - chatListView.computeVerticalScrollOffset() - chatListView.computeVerticalScrollExtent(); if (maxScrollOffset < 0) maxScrollOffset = 0; if (scrollY > maxScrollOffset) { @@ -9354,6 +10024,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatScrollHelperCallback.scrollTo = object; chatScrollHelperCallback.lastBottom = false; chatScrollHelperCallback.lastItemOffset = yOffset; + chatScrollHelper.setScrollDirection(scrollDirection); chatScrollHelper.scrollToPosition(position, yOffset, false, true); canShowPagedownButton = true; updatePagedownButtonVisibility(true); @@ -9388,9 +10059,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not postponedScrollIsCanceled = false; waitingForLoad.add(lastLoadIndex); postponedScrollToLastMessageQueryIndex = lastLoadIndex; + postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; - getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, isThreadChat() || AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); - //emptyViewContainer.setVisibility(View.INVISIBLE); + getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, isThreadChat() || AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { View child = chatListView.getChildAt(0); if (child != null && child.getTop() <= 0) { @@ -9603,7 +10274,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (requestCode == 4 && chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkStorage(); - } else if (requestCode == 5 && chatAttachAlert != null) { + } else if ((requestCode == 5 || requestCode == 30) && chatAttachAlert != null) { chatAttachAlert.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } else if ((requestCode == 17 || requestCode == 18) && chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkCamera(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED); @@ -9867,14 +10538,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount--; } - if (!messageObject.canDeleteMessage(inScheduleMode, currentChat)) { + if (!messageObject.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat)) { cantDeleteMessagesCount--; } - if (inScheduleMode || !messageObject.canForwardMessage()) { + if (chatMode == MODE_SCHEDULED || !messageObject.canForwardMessage()) { cantForwardMessagesCount--; } else { canForwardMessagesCount--; } + if (messageObject.isMusic()) { + canSaveMusicCount--; + } else if (messageObject.isDocument()) { + canSaveDocumentsCount--; + } else { + cantSaveMessagesCount--; + } } else { if (selectedMessagesIds[0].size() + selectedMessagesIds[1].size() >= 100) { return; @@ -9889,14 +10567,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount++; } - if (!messageObject.canDeleteMessage(inScheduleMode, currentChat)) { + if (!messageObject.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat)) { cantDeleteMessagesCount++; } - if (inScheduleMode || !messageObject.canForwardMessage()) { + if (chatMode == MODE_SCHEDULED || !messageObject.canForwardMessage()) { cantForwardMessagesCount++; } else { canForwardMessagesCount++; } + if (messageObject.isMusic()) { + canSaveMusicCount++; + } else if (messageObject.isDocument()) { + canSaveDocumentsCount++; + } else { + cantSaveMessagesCount++; + } if (outside) { showTextSelectionHint(messageObject); } @@ -9912,6 +10597,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not hideActionMode(); updatePinnedMessageView(true); } else { + ActionBarMenuItem saveItem = actionBar.createActionMode().getItem(save_to); ActionBarMenuItem copyItem = actionBar.createActionMode().getItem(copy); ActionBarMenuItem starItem = actionBar.createActionMode().getItem(star); ActionBarMenuItem editItem = actionBar.createActionMode().getItem(edit); @@ -9947,6 +10633,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forwardButton.setAlpha(cantForwardMessagesCount == 0 ? 1.0f : 0.5f); } } + if (saveItem != null) { + saveItem.setVisibility(((canSaveMusicCount > 0 && canSaveDocumentsCount == 0) || (canSaveMusicCount == 0 && canSaveDocumentsCount > 0)) && cantSaveMessagesCount == 0 ? View.VISIBLE : View.GONE); + saveItem.setContentDescription(canSaveMusicCount > 0 ? LocaleController.getString("SaveToMusic", R.string.SaveToMusic) : LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + } int copyVisible = copyItem.getVisibility(); int starVisible = starItem.getVisibility(); @@ -9980,7 +10670,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int newVisibility; - if (inScheduleMode || !allowChatActions || selectedCount == 0 || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { + if (chatMode == MODE_SCHEDULED || !allowChatActions || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { newVisibility = View.GONE; } else if (selectedCount == 1) { newVisibility = View.VISIBLE; @@ -10150,12 +10840,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (UserObject.isReplyUser(currentUser)) { avatarContainer.setTitle(LocaleController.getString("RepliesTitle", R.string.RepliesTitle)); - } else if (inScheduleMode) { + } else if (chatMode == MODE_SCHEDULED) { if (UserObject.isUserSelf(currentUser)) { avatarContainer.setTitle(LocaleController.getString("Reminders", R.string.Reminders)); } else { avatarContainer.setTitle(LocaleController.getString("ScheduledMessages", R.string.ScheduledMessages)); } + } else if (chatMode == MODE_PINNED) { + avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } else if (currentChat != null) { avatarContainer.setTitle(currentChat.title, currentChat.scam); } else if (currentUser != null) { @@ -10174,6 +10866,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setParentActivityTitle(avatarContainer.getTitleTextView().getText()); } + private int getPinnedMessagesCount() { + return Math.max(loadedPinnedMessagesCount, totalPinnedMessagesCount); + } + private void updateBotButtons() { if (headerItem == null || currentUser == null || currentEncryptedChat != null || !currentUser.bot) { return; @@ -10209,7 +10905,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateTitleIcons() { - if (avatarContainer == null || inScheduleMode) { + if (avatarContainer == null || chatMode != 0) { return; } Drawable rightIcon = getMessagesController().isDialogMuted(dialog_id) ? Theme.chat_muteIconDrawable : null; @@ -10360,7 +11056,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openVideoEditor(videoPath, null); } } else { - if (editingMessageObject == null && inScheduleMode) { + if (editingMessageObject == null && chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, 0, editingMessageObject, notify, scheduleDate); @@ -10432,27 +11128,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!doNotRemoveLoadIndex && !openAnimationEnded) { getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, - NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); + NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } int index = waitingForLoad.indexOf(queryLoadIndex); int currentUserId = getUserConfig().getClientUserId(); - boolean schedule = (Boolean) args[14]; + int mode = (Integer) args[14]; boolean isCache = (Boolean) args[3]; boolean postponedScroll = postponedScrollToLastMessageQueryIndex > 0 && queryLoadIndex == postponedScrollToLastMessageQueryIndex; if (index == -1) { - if (inScheduleMode && schedule && !isCache) { + if (chatMode == MODE_SCHEDULED && mode == MODE_SCHEDULED && !isCache) { waitingForReplyMessageLoad = true; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } return; } else if (!doNotRemoveLoadIndex) { waitingForLoad.remove(index); } ArrayList messArr = (ArrayList) args[2]; - if (inScheduleMode != schedule) { - if (!inScheduleMode) { + if (chatMode != mode) { + if (chatMode != MODE_SCHEDULED) { scheduledMessagesCount = messArr.size(); updateScheduledInterface(true); } @@ -10461,7 +11157,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean createUnreadLoading = false; boolean showDateAfter = waitingForReplyMessageLoad; if (waitingForReplyMessageLoad) { - if (!inScheduleMode && !createUnreadMessageAfterIdLoading) { + if (chatMode != MODE_SCHEDULED && !createUnreadMessageAfterIdLoading) { boolean found = false; for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); @@ -10488,7 +11184,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(); - if (!inScheduleMode) { + if (chatMode == 0) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -10528,7 +11224,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (load_type == 0 && isCache && messArr.size() < count) { postponedScrollToLastMessageQueryIndex = lastLoadIndex; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, count, 0, 0, false, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, count, 0, 0, false, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); return; } @@ -10562,7 +11258,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(); - if (!inScheduleMode) { + if (chatMode == 0) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -10603,7 +11299,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forwardEndReached[0] = false; minMessageId[0] = 0; } - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { endReached[0] = cacheEndReached[0] = true; forwardEndReached[0] = forwardEndReached[0] = true; } @@ -10676,6 +11372,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forwardEndReached[0] = true; } } + if (chatMode == MODE_PINNED) { + endReached[loadIndex] = true; + } if (!threadMessageAdded && isThreadChat() && (load_type == 0 && messArr.size() < count || (load_type == 2 || load_type == 3) && endReached[0])) { TLRPC.Message msg = new TLRPC.TL_message(); @@ -10707,7 +11406,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Collections.reverse(messArr); } if (currentEncryptedChat == null) { - getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, inScheduleMode, null); + getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode == MODE_SCHEDULED, null); } int approximateHeightSum = 0; if ((load_type == 2 || load_type == 1) && messArr.isEmpty() && !isCache) { @@ -10744,7 +11443,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentUser.self) { obj.messageOwner.out = true; } - if (!inScheduleMode && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { + if (chatMode != MODE_SCHEDULED && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } } @@ -10801,7 +11500,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not continue; } - if (needAnimateToMessage != null && needAnimateToMessage.getId() == messageId && messageId < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { + if (needAnimateToMessage != null && needAnimateToMessage.getId() == messageId && messageId < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && chatMode != MODE_SCHEDULED) { obj = needAnimateToMessage; animatingMessageObjects.add(obj); needAnimateToMessage = null; @@ -10814,7 +11513,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { dateMsg.message = LocaleController.getString("MessageScheduledUntilOnline", R.string.MessageScheduledUntilOnline); } else { @@ -11199,7 +11898,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (first && messages.size() > 0) { first = false; if (isThreadChat()) { - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); } } if (messages.isEmpty() && currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { @@ -11220,7 +11919,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (newRowsCount == 0 && mergeDialogId != 0 && loadIndex == 0) { getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, - NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); + NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } if (showDateAfter) { showFloatingDateView(false); @@ -11252,14 +11951,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (object != null) { int k = messages.indexOf(object); if (k >= 0) { - removeSelectedMessageHighlight(); + int fromPosition = chatLayoutManager.findFirstVisibleItemPosition(); highlightMessageId = object.getId(); + int direction; + if (postponedScrollMinMessageId != 0) { + if (highlightMessageId < 0 && postponedScrollMinMessageId < 0) { + direction = highlightMessageId < postponedScrollMinMessageId ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + } else { + direction = highlightMessageId > postponedScrollMinMessageId ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + } + } else { + direction = fromPosition > k ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + } + chatScrollHelper.setScrollDirection(direction); + + if (!needSelectFromMessageId) { + removeSelectedMessageHighlight(); + } int yOffset = getScrollOffsetForMessage(object); chatScrollHelperCallback.scrollTo = object; chatScrollHelperCallback.lastBottom = false; chatScrollHelperCallback.lastItemOffset = yOffset; - chatScrollHelper.scrollToPosition(chatAdapter.messagesStartRow + messages.indexOf(object), yOffset, false, true); + chatScrollHelper.scrollToPosition(chatAdapter.messagesStartRow + k, yOffset, false, true); } } } @@ -11275,8 +11989,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (alertTextView != null) { alertTextView.invalidate(); } - if (pinnedMessageTextView != null) { - pinnedMessageTextView.invalidate(); + for (int a = 0; a < 2; a++) { + if (pinnedMessageTextView[a] != null) { + pinnedMessageTextView[a].invalidate(); + } } if (mentionListView != null) { mentionListView.invalidateViews(); @@ -11361,586 +12077,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.didReceiveNewMessages) { long did = (Long) args[0]; + ArrayList arr = (ArrayList) args[1]; if (did == dialog_id) { boolean scheduled = (Boolean) args[2]; - if (scheduled != inScheduleMode) { - if (!inScheduleMode && !isPaused && forwardingMessages == null) { - ArrayList arr = (ArrayList) args[1]; + if (scheduled != (chatMode == MODE_SCHEDULED)) { + if (chatMode != MODE_SCHEDULED && !isPaused && forwardingMessages == null) { if (!arr.isEmpty() && arr.get(0).getId() < 0) { openScheduledMessages(); } } return; } - int currentUserId = getUserConfig().getClientUserId(); - boolean updateChat = false; - boolean hasFromMe = false; - ArrayList arr = (ArrayList) args[1]; - - if (chatListItemAniamtor != null) { - chatListItemAniamtor.setShouldAnimateEnterFromBottom(true); - } - - boolean notifiedSearch = false; - LongSparseArray scheduledGroupReplacement = null; - for (int a = 0; a < arr.size(); a++) { - MessageObject messageObject = arr.get(a); - int messageId = messageObject.getId(); - if (threadMessageId != 0) { - if (messageId > 0 && messageId <= (messageObject.isOut() ? threadMaxOutboxReadId : threadMaxInboxReadId)) { - messageObject.setIsRead(); - } - } - if (messageObject.isDice()) { - messageObject.wasUnread = true; - } - if (inScheduleMode && messageObject.hasValidGroupId() && messagesDict[0].indexOfKey(messageObject.getId()) >= 0) { - long groupId = messageObject.getGroupId(); - if (scheduledGroupReplacement == null) { - scheduledGroupReplacement = new LongSparseArray<>(); - } - Long localId = scheduledGroupReplacement.get(groupId); - if (localId == null) { - localId = Utilities.random.nextLong(); - scheduledGroupReplacement.put(groupId, localId); - } - messageObject.localGroupId = localId; - } - if (messageObject.isOut()) { - if (!notifiedSearch) { - notifiedSearch = true; - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); - } - if (currentChat != null && currentChat.slowmode_enabled && messageObject.isSent() && !inScheduleMode) { - if (chatInfo != null) { - int date = messageObject.messageOwner.date + chatInfo.slowmode_seconds; - int currentTime = getConnectionsManager().getCurrentTime(); - if (date > getConnectionsManager().getCurrentTime()) { - chatInfo.slowmode_next_send_date = Math.max(chatInfo.slowmode_next_send_date, Math.min(currentTime + chatInfo.slowmode_seconds, date)); - if (chatActivityEnterView != null) { - chatActivityEnterView.setSlowModeTimer(chatInfo.slowmode_next_send_date); - } - } - } - getMessagesController().loadFullChat(currentChat.id, 0, true); - } - } - if (currentChat != null) { - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || - messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser && messageObject.messageOwner.action.users.contains(currentUserId)) { - TLRPC.Chat newChat = getMessagesController().getChat(currentChat.id); - if (newChat != null) { - currentChat = newChat; - checkActionBarMenu(); - updateBottomOverlay(); - if (avatarContainer != null) { - avatarContainer.updateSubtitle(true); - } - } - } - } else if (inlineReturn != 0) { - if (messageObject.messageOwner.reply_markup != null) { - for (int b = 0; b < messageObject.messageOwner.reply_markup.rows.size(); b++) { - TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(b); - for (int c = 0; c < row.buttons.size(); c++) { - TLRPC.KeyboardButton button = row.buttons.get(c); - if (button instanceof TLRPC.TL_keyboardButtonSwitchInline) { - processSwitchButton((TLRPC.TL_keyboardButtonSwitchInline) button); - break; - } - } - } - } - } - if (messageObject.getReplyMsgId() != 0 && messageObject.replyMessageObject == null) { - messageObject.replyMessageObject = messagesDict[0].get(messageObject.getReplyMsgId()); - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { - messageObject.generatePinMessageText(null, null); - } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { - messageObject.generateGameMessageText(null); - } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { - messageObject.generatePaymentSentMessageText(null); - } - if (messageObject.isMegagroup() && messageObject.replyMessageObject != null && messageObject.replyMessageObject.messageOwner != null) { - messageObject.replyMessageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; - } - } - } - - if (inScheduleMode && !arr.isEmpty()) { - replaceMessageObjects(arr, 0, true); - } - - boolean needMoveScrollToLastMessage = false; - - boolean reloadMegagroup = false; - if (!forwardEndReached[0]) { - int currentMaxDate = Integer.MIN_VALUE; - int currentMinMsgId = Integer.MIN_VALUE; - if (currentEncryptedChat != null) { - currentMinMsgId = Integer.MAX_VALUE; - } - - for (int a = 0; a < arr.size(); a++) { - MessageObject obj = arr.get(a); - if (threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { - continue; - } - int messageId = obj.getId(); - - if (obj.isOut() && waitingForSendingMessageLoad) { - waitingForSendingMessageLoad = false; - chatActivityEnterView.hideTopView(true); - if (changeBoundAnimator != null) { - changeBoundAnimator.start(); - } - } - - if (!inScheduleMode && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { - obj.setIsRead(); - } - TLRPC.MessageAction action = obj.messageOwner.action; - if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - avatarContainer.setTime(((TLRPC.TL_decryptedMessageActionSetMessageTTL) action.encryptedAction).ttl_seconds); - } - if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { - migrateToNewChat(obj); - return; - } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { - reloadMegagroup = true; - } - if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { - needAnimateToMessage = obj; - } - if (obj.isOut() && obj.wasJustSent) { - scrollToLastMessage(); - return; - } - if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { - continue; - } - if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { - continue; - } - if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { - continue; - } - if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { - continue; - } - if (threadMessageObject != null && obj.isReply()) { - int mid = obj.getReplyAnyMsgId(); - if (threadMessageObject.getId() == mid) { - threadMessageObject.messageOwner.replies.replies++; - } - } - addToPolls(obj, null); - obj.checkLayout(); - currentMaxDate = Math.max(currentMaxDate, obj.messageOwner.date); - if (messageId > 0) { - currentMinMsgId = Math.max(messageId, currentMinMsgId); - last_message_id = Math.max(last_message_id, messageId); - } else if (currentEncryptedChat != null) { - currentMinMsgId = Math.min(messageId, currentMinMsgId); - last_message_id = Math.min(last_message_id, messageId); - } - - if (threadMessageId == 0) { - if (obj.messageOwner.mentioned && obj.isContentUnread()) { - newMentionsCount++; - } - newUnreadMessageCount++; - } - if (obj.type == 10 || obj.type == 11) { - updateChat = true; - } - } - if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { - pagedownButtonCounter.setVisibility(View.VISIBLE); - if (prevSetUnreadCount != newUnreadMessageCount) { - prevSetUnreadCount = newUnreadMessageCount; - pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount)); - } - } - if (newMentionsCount != 0 && mentiondownButtonCounter != null) { - mentiondownButtonCounter.setVisibility(View.VISIBLE); - mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); - showMentionDownButton(true, true); - } - - updateVisibleRows(); - } else { - LongSparseArray newGroups = null; - HashMap> webpagesToReload = null; - if (BuildVars.LOGS_ENABLED) { - FileLog.d("received new messages " + arr.size() + " in dialog " + dialog_id); - } - for (int a = 0; a < arr.size(); a++) { - MessageObject obj = arr.get(a); - if (obj.scheduled != inScheduleMode || threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { - continue; - } - int placeToPaste = -1; - int messageId = obj.getId(); - if (inScheduleMode && messagesDict[0].indexOfKey(messageId) >= 0) { - MessageObject removed = messagesDict[0].get(messageId); - messagesDict[0].remove(messageId); - if (removed != null) { - int index = messages.indexOf(removed); - messages.remove(index); - ArrayList dayArr = messagesByDays.get(removed.dateKey); - dayArr.remove(removed); - if (dayArr.isEmpty()) { - messagesByDays.remove(removed.dateKey); - if (index >= 0 && index < messages.size()) { - messages.remove(index); - } - } - if (removed.hasValidGroupId()) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); - groupedMessages.messages.remove(removed); - if (newGroups == null) { - newGroups = new LongSparseArray<>(); - } - newGroups.put(groupedMessages.groupId, groupedMessages); - } - if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(false); - } - } - } - if (isSecretChat()) { - checkSecretMessageForLocation(obj); - } - if (!inScheduleMode && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { - obj.setIsRead(); - } - TLRPC.MessageAction action = obj.messageOwner.action; - if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - avatarContainer.setTime(((TLRPC.TL_decryptedMessageActionSetMessageTTL) action.encryptedAction).ttl_seconds); - } - if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { - continue; - } - if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { - continue; - } - if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { - continue; - } - if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { - continue; - } - if (threadMessageObject != null && threadMessageObject.messageOwner.replies != null && obj.isReply()) { - int mid = obj.getReplyAnyMsgId(); - if (threadMessageObject.getId() == mid) { - threadMessageObject.messageOwner.replies.replies++; - } - } - addToPolls(obj, null); - if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { - animatingMessageObjects.add(obj); - } - - MessageObject.GroupedMessages groupedMessages; - if (obj.hasValidGroupId()) { - groupedMessages = groupedMessagesMap.get(obj.getGroupId()); - if (groupedMessages == null) { - groupedMessages = new MessageObject.GroupedMessages(); - groupedMessages.groupId = obj.getGroupId(); - groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); - } - if (newGroups == null) { - newGroups = new LongSparseArray<>(); - } - newGroups.put(groupedMessages.groupId, groupedMessages); - groupedMessages.messages.add(obj); - } else { - groupedMessages = null; - } - - if (groupedMessages != null) { - int size = groupedMessages.messages.size(); - MessageObject messageObject = size > 1 ? groupedMessages.messages.get(groupedMessages.messages.size() - 2) : null; - if (messageObject != null) { - placeToPaste = messages.indexOf(messageObject); - } - } - - if (placeToPaste == -1) { - if (!obj.scheduled && obj.messageOwner.id < 0 || messages.isEmpty()) { - placeToPaste = 0; - } else { - int size = messages.size(); - for (int b = 0; b < size; b++) { - MessageObject lastMessage = messages.get(b); - if (lastMessage.type >= 0 && lastMessage.messageOwner.date > 0) { - if (!inScheduleMode && lastMessage.messageOwner.id > 0 && obj.messageOwner.id > 0 && lastMessage.messageOwner.id < obj.messageOwner.id || lastMessage.messageOwner.date <= obj.messageOwner.date) { - MessageObject.GroupedMessages lastGroupedMessages; - if (lastMessage.getGroupId() != 0) { - lastGroupedMessages = groupedMessagesMap.get(lastMessage.getGroupId()); - if (lastGroupedMessages != null && lastGroupedMessages.messages.size() == 0) { - lastGroupedMessages = null; - } - } else { - lastGroupedMessages = null; - } - if (lastGroupedMessages == null) { - placeToPaste = b; - } else { - placeToPaste = messages.indexOf(lastGroupedMessages.messages.get(lastGroupedMessages.messages.size() - 1)); - } - break; - } - } - } - if (placeToPaste == -1 || placeToPaste > messages.size()) { - placeToPaste = messages.size(); - } - } - } - if (currentEncryptedChat != null && obj.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && obj.messageOwner.media.webpage instanceof TLRPC.TL_webPageUrlPending) { - if (webpagesToReload == null) { - webpagesToReload = new HashMap<>(); - } - ArrayList arrayList = webpagesToReload.get(obj.messageOwner.media.webpage.url); - if (arrayList == null) { - arrayList = new ArrayList<>(); - webpagesToReload.put(obj.messageOwner.media.webpage.url, arrayList); - } - arrayList.add(obj); - } - obj.checkLayout(); - if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { - migrateToNewChat(obj); - if (newGroups != null) { - for (int b = 0; b < newGroups.size(); b++) { - newGroups.valueAt(b).calculate(); - } - } - return; - } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { - reloadMegagroup = true; - } - if (minDate[0] == 0 || obj.messageOwner.date < minDate[0]) { - minDate[0] = obj.messageOwner.date; - } - - if (obj.isOut() && !obj.messageOwner.from_scheduled) { - removeUnreadPlane(true); - hideDistanceView(); - hasFromMe = true; - } - - if (messageId > 0) { - maxMessageId[0] = Math.min(messageId, maxMessageId[0]); - minMessageId[0] = Math.max(messageId, minMessageId[0]); - } else if (currentEncryptedChat != null) { - maxMessageId[0] = Math.max(messageId, maxMessageId[0]); - minMessageId[0] = Math.min(messageId, minMessageId[0]); - } - maxDate[0] = Math.max(maxDate[0], obj.messageOwner.date); - messagesDict[0].put(messageId, obj); - ArrayList dayArray = messagesByDays.get(obj.dateKey); - if (placeToPaste > messages.size()) { - placeToPaste = messages.size(); - } - if (dayArray == null) { - dayArray = new ArrayList<>(); - messagesByDays.put(obj.dateKey, dayArray); - TLRPC.Message dateMsg = new TLRPC.TL_message(); - if (inScheduleMode) { - if (obj.messageOwner.date == 0x7ffffffe) { - dateMsg.message = LocaleController.getString("MessageScheduledUntilOnline", R.string.MessageScheduledUntilOnline); - } else { - dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); - } - } else { - dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); - } - dateMsg.id = 0; - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 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 = lastStableId++; - messages.add(placeToPaste, dateObj); - if (chatAdapter != null) { - chatAdapter.notifyItemInserted(placeToPaste); - } - } - if (!obj.isOut() || obj.messageOwner.from_scheduled) { - if (paused && placeToPaste == 0) { - if (!scrollToTopUnReadOnResume && unreadMessageObject != null) { - removeMessageObject(unreadMessageObject); - if (placeToPaste > 0) { - placeToPaste--; - } - unreadMessageObject = null; - } - if (unreadMessageObject == null) { - TLRPC.Message dateMsg = new TLRPC.TL_message(); - dateMsg.message = ""; - dateMsg.id = 0; - MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); - dateObj.type = 6; - dateObj.contentType = 2; - dateObj.stableId = lastStableId++; - messages.add(0, dateObj); - if (chatAdapter != null) { - chatAdapter.notifyItemInserted(0); - } - unreadMessageObject = dateObj; - scrollToMessage = unreadMessageObject; - scrollToMessagePosition = -10000; - scrollToTopUnReadOnResume = true; - } - } - } - - dayArray.add(0, obj); - - if (chatAdapter != null && placeToPaste >= 0 && placeToPaste < messages.size()) { - MessageObject prevMessage = messages.get(placeToPaste); - if (prevMessage.hasValidGroupId() && prevMessage.getGroupId() != obj.getGroupId()) { - MessageObject.GroupedMessages group = groupedMessagesMap.get(prevMessage.getGroupId()); - if (group != null && group.messages.size() > 1) { - int size = group.messages.size(); - chatAdapter.notifyItemRangeChanged(1, size - 1); - } - } - } - obj.stableId = lastStableId++; - messages.add(placeToPaste, obj); - if (placeToPaste == 0) { - needMoveScrollToLastMessage = true; - } - if (chatAdapter != null) { - chatAdapter.notifyItemChanged(placeToPaste); - chatAdapter.notifyItemInserted(placeToPaste); - } - if (obj.isOut() && waitingForSendingMessageLoad) { - waitingForSendingMessageLoad = false; - chatActivityEnterView.hideTopView(true); - if (changeBoundAnimator != null) { - changeBoundAnimator.start(); - } - } - if (threadMessageId == 0) { - if (!obj.isOut() && obj.messageOwner.mentioned && obj.isContentUnread()) { - newMentionsCount++; - } - newUnreadMessageCount++; - } - if (obj.type == 10 || obj.type == 11) { - updateChat = true; - } - } - if (webpagesToReload != null) { - getMessagesController().reloadWebPages(dialog_id, webpagesToReload, inScheduleMode); - } - if (newGroups != null) { - for (int a = 0; a < newGroups.size(); a++) { - MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); - int oldCount = groupedMessages.posArray.size(); - groupedMessages.calculate(); - int newCount = groupedMessages.posArray.size(); - if (newCount - oldCount > 0 && chatAdapter != null) { - int index = messages.indexOf(groupedMessages.messages.get(groupedMessages.messages.size() - 1)); - if (index >= 0) { - chatAdapter.notifyItemRangeChanged(index, newCount); - } - } - } - } - - showProgressView(false); - if (chatAdapter == null) { - scrollToTopOnResume = true; - } - - if (chatListView != null && chatAdapter != null) { - int lastVisible = chatLayoutManager.findFirstVisibleItemPosition(); - if (lastVisible == RecyclerView.NO_POSITION) { - lastVisible = 0; - } - View child = chatLayoutManager.findViewByPosition(lastVisible); - int diff; - if (child != null) { - diff = child.getBottom() - chatListView.getMeasuredHeight(); - } else { - diff = 0; - } - if (lastVisible == 0 && diff <= AndroidUtilities.dp(5) || hasFromMe) { - newUnreadMessageCount = 0; - if (!firstLoading && !inScheduleMode) { - if (paused) { - scrollToTopOnResume = true; - } else { - forceScrollToTop = true; - moveScrollToLastMessage(); - } - } - } else { - if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { - pagedownButtonCounter.setVisibility(View.VISIBLE); - if (prevSetUnreadCount != newUnreadMessageCount) { - prevSetUnreadCount = newUnreadMessageCount; - pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount)); - } - } - canShowPagedownButton = true; - updatePagedownButtonVisibility(true); - } - if (newMentionsCount != 0 && mentiondownButtonCounter != null) { - mentiondownButtonCounter.setVisibility(View.VISIBLE); - mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); - showMentionDownButton(true, true); - } - } else { - scrollToTopOnResume = true; - } - } - if (inScheduleMode && !arr.isEmpty()) { - MessageObject messageObject = arr.get(0); - int mid = messageObject.getId(); - if (mid < 0) { - if (chatListItemAniamtor != null) { - chatListItemAniamtor.setShouldAnimateEnterFromBottom(needMoveScrollToLastMessage); - } - if (needMoveScrollToLastMessage) { - moveScrollToLastMessage(); - } else { - int index = messages.indexOf(messageObject); - if (chatLayoutManager != null && index > 0 && (chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index) != null || chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index - 1) != null)) { - chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(messageObject), getScrollOffsetForMessage(messageObject), false); - } else { - AndroidUtilities.runOnUIThread(() -> scrollToMessageId(mid, 0, false, 0, true)); - } - } - - } - } - if (!messages.isEmpty() && botUser != null && botUser.length() == 0) { - botUser = null; - updateBottomOverlay(); - } - if (updateChat) { - updateTitle(); - checkAndUpdateAvatar(); - } - if (reloadMegagroup) { - getMessagesController().loadFullChat(currentChat.id, 0, true); - } - checkWaitingForReplies(); - updateReplyMessageHeader(true); + processNewMessages(arr); } else if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && chatInfo != null && did == -chatInfo.linked_chat_id) { - ArrayList arr = (ArrayList) args[1]; for (int a = 0, N = arr.size(); a < N; a++) { MessageObject messageObject = arr.get(a); if (messageObject.isReply()) { @@ -12024,7 +12173,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int inbox = (Integer) args[2]; int outbox = (Integer) args[3]; - boolean updated = false; if (inbox > threadMaxInboxReadId) { threadMaxInboxReadId = inbox; for (int a = 0, size2 = messages.size(); a < size2; a++) { @@ -12035,7 +12183,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } obj.setIsRead(); - updated = true; + if (chatAdapter != null) { + chatAdapter.invalidateRowWithMessageObject(obj); + } } } } @@ -12049,15 +12199,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } obj.setIsRead(); - updated = true; + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(obj, false); + } } } } - if (updated) { - updateVisibleRows(); - } } else if (id == NotificationCenter.messagesRead) { - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { return; } SparseLongArray inbox = (SparseLongArray) args[0]; @@ -12077,6 +12226,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } obj.setIsRead(); + if (chatAdapter != null) { + chatAdapter.invalidateRowWithMessageObject(obj); + } updated = true; newUnreadMessageCount--; } @@ -12115,44 +12267,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0, size2 = messages.size(); a < size2; a++) { MessageObject obj = messages.get(a); if (obj.isOut() && obj.getId() > 0 && obj.getId() <= messageId) { - if (!obj.isUnread()) { - break; - } obj.setIsRead(); - updated = true; + if (chatAdapter != null) { + chatAdapter.invalidateRowWithMessageObject(obj); + } } } break; } } - if (updated) { - updateVisibleRows(); - } } else if (id == NotificationCenter.historyCleared) { long did = (Long) args[0]; if (did != dialog_id) { return; } int max_id = (Integer) args[1]; - boolean updated = false; + if (!pinnedMessageIds.isEmpty()) { + pinnedMessageIds.clear(); + pinnedMessageObjects.clear(); + currentPinnedMessageId = 0; + loadedPinnedMessagesCount = 0; + totalPinnedMessagesCount = 0; + updatePinnedMessageView(true); + } + boolean updated = false; for (int b = 0; b < messages.size(); b++) { MessageObject obj = messages.get(b); int mid = obj.getId(); if (mid <= 0 || mid > max_id) { continue; } - if (chatInfo != null && chatInfo.pinned_msg_id == mid) { - pinnedMessageObject = null; - chatInfo.pinned_msg_id = 0; - getMessagesStorage().updateChatPinnedMessage(chatInfo.id, 0); - updatePinnedMessageView(true); - } else if (userInfo != null && userInfo.pinned_msg_id == mid) { - pinnedMessageObject = null; - userInfo.pinned_msg_id = 0; - getMessagesStorage().updateUserPinnedMessage(chatInfo.id, 0); - updatePinnedMessageView(true); - } messages.remove(b); b--; messagesDict[0].remove(mid); @@ -12186,7 +12331,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not maxDate[0] = maxDate[1] = Integer.MIN_VALUE; minDate[0] = minDate[1] = 0; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loading = true; } else { if (botButtons != null) { @@ -12210,230 +12355,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.messagesDeleted) { boolean scheduled = (Boolean) args[2]; - if (scheduled != inScheduleMode) { + if (scheduled != (chatMode == MODE_SCHEDULED)) { return; } ArrayList markAsDeletedMessages = (ArrayList) args[0]; - ArrayList removedIndexes = new ArrayList<>(); - int channelId = (Integer) args[1]; - int loadIndex = 0; - if (ChatObject.isChannel(currentChat)) { - if (channelId == 0 && mergeDialogId != 0) { - loadIndex = 1; - } else if (channelId == currentChat.id) { - loadIndex = 0; - } else { - return; - } - } else if (channelId != 0) { - return; - } - boolean updated = false; - LongSparseArray newGroups = null; - LongSparseArray newGroupsSizes = null; - int size = markAsDeletedMessages.size(); - boolean updatedSelected = false; - boolean updatedSelectedLast = false; - boolean updateScheduled = false; - boolean hasChatInBack = false; - boolean updatedReplies = false; - - if (threadMessageObject != null && parentLayout != null) { - for (int a = 0, N = parentLayout.fragmentsStack.size() - 1; a < N; a++) { - BaseFragment fragment = parentLayout.fragmentsStack.get(a); - if (fragment != this && fragment instanceof ChatActivity) { - ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.inScheduleMode == inScheduleMode) { - hasChatInBack = true; - break; - } - } - } - } - - int commentsDeleted = 0; - for (int a = 0; a < size; a++) { - Integer ids = markAsDeletedMessages.get(a); - MessageObject obj = messagesDict[loadIndex].get(ids); - if (loadIndex == 0 && (chatInfo != null && chatInfo.pinned_msg_id == ids || userInfo != null && userInfo.pinned_msg_id == ids)) { - pinnedMessageObject = null; - if (chatInfo != null) { - chatInfo.pinned_msg_id = 0; - } else if (userInfo != null) { - userInfo.pinned_msg_id = 0; - } - getMessagesStorage().updateChatPinnedMessage(channelId, 0); - updatePinnedMessageView(true); - } - if (obj != null) { - if (obj.messageOwner.reply_to != null) { - int replyId = obj.getReplyAnyMsgId(); - if (threadMessageObject != null && threadMessageObject.getId() == replyId) { - if (!hasChatInBack && threadMessageObject.hasReplies()) { - threadMessageObject.messageOwner.replies.replies--; - } - if (replyOriginalMessageId != 0) { - commentsDeleted++; - } - updatedReplies = true; - } else { - MessageObject replyObject = messagesDict[loadIndex].get(replyId); - if (replyObject != null && replyObject.hasReplies()) { - replyObject.messageOwner.replies.replies--; - replyObject.viewsReloaded = false; - } - } - } - obj.deleted = true; - if (editingMessageObject == obj) { - hideFieldPanel(true); - } - int index = messages.indexOf(obj); - if (index != -1) { - if (obj.scheduled) { - scheduledMessagesCount--; - updateScheduled = true; - } - if (selectedMessagesIds[loadIndex].indexOfKey(ids) >= 0) { - updatedSelected = true; - addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); - } - MessageObject removed = messages.remove(index); - if (chatAdapter != null) { - removedIndexes.add(chatAdapter.messagesStartRow + index); - } - if (removed.getGroupId() != 0) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); - if (groupedMessages != null) { - if (newGroups == null) { - newGroups = new LongSparseArray<>(); - newGroupsSizes = new LongSparseArray<>(); - } - newGroups.put(groupedMessages.groupId, groupedMessages); - if (newGroupsSizes.get(groupedMessages.groupId) == null) { - newGroupsSizes.put(groupedMessages.groupId, groupedMessages.messages.size()); - } - groupedMessages.messages.remove(obj); - } - } - messagesDict[loadIndex].remove(ids); - ArrayList dayArr = messagesByDays.get(obj.dateKey); - if (dayArr != null) { - dayArr.remove(obj); - if (dayArr.isEmpty()) { - messagesByDays.remove(obj.dateKey); - if (index >= 0 && index < messages.size()) { - messages.remove(index); - if (chatAdapter != null) { - removedIndexes.add(chatAdapter.messagesStartRow + index); - } - } - } - } - updated = true; - } - } - } - if (updatedReplies) { - updateReplyMessageHeader(true); - } - if (commentsDeleted != 0) { - getNotificationCenter().postNotificationName(NotificationCenter.changeRepliesCounter, replyOriginalChat.id, replyOriginalMessageId, -commentsDeleted); - getMessagesStorage().updateRepliesCount(replyOriginalChat.id, replyOriginalMessageId, null, 0, -commentsDeleted); - } - if (updatedSelected) { - if (!updatedSelectedLast) { - addToSelectedMessages(null, false, true); - } - updateActionModeTitle(); - } - if (newGroups != null) { - for (int a = 0; a < newGroups.size(); a++) { - MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); - if (chatListItemAniamtor != null) { - if (groupedMessages.messages.size() == 1) { - chatListItemAniamtor.groupWillTransformToSingleMessage(groupedMessages); - } else { - chatListItemAniamtor.groupWillChanged(groupedMessages); - } - } - - if (groupedMessages.messages.isEmpty()) { - groupedMessagesMap.remove(groupedMessages.groupId); - } else { - groupedMessages.calculate(); - MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); - int index = messages.indexOf(messageObject); - if (index >= 0) { - if (chatAdapter != null) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); - } - } - } - } - } - if (messages.isEmpty()) { - if (!endReached[0] && !loading) { - showProgressView(false); - if (chatListView != null) { - chatListView.setEmptyView(null); - } - if (currentEncryptedChat == null) { - maxMessageId[0] = maxMessageId[1] = Integer.MAX_VALUE; - minMessageId[0] = minMessageId[1] = Integer.MIN_VALUE; - } else { - maxMessageId[0] = maxMessageId[1] = Integer.MIN_VALUE; - minMessageId[0] = minMessageId[1] = Integer.MAX_VALUE; - } - maxDate[0] = maxDate[1] = Integer.MIN_VALUE; - minDate[0] = minDate[1] = 0; - waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); - loading = true; - } else { - if (botButtons != null) { - botButtons = null; - if (chatActivityEnterView != null) { - chatActivityEnterView.setButtons(null, false); - } - } - if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { - botUser = ""; - updateBottomOverlay(); - } - } - canShowPagedownButton = false; - updatePagedownButtonVisibility(true); - showMentionDownButton(false, true); - } - if (updated) { - if (chatAdapter != null) { - for (int a = 0, N = removedIndexes.size(); a < N; a++) { - chatAdapter.notifyItemRemoved(removedIndexes.get(a)); - } - if (!isThreadChat() || messages.size() <= 3) { - removeUnreadPlane(false); - } - chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, messages.size()); - } - updateVisibleRows(); - } else if (threadMessageId == 0) { - first_unread_id = 0; - last_message_id = 0; - createUnreadMessageAfterId = 0; - removeMessageObject(unreadMessageObject); - unreadMessageObject = null; - if (pagedownButtonCounter != null) { - pagedownButtonCounter.setVisibility(View.INVISIBLE); - } - } - if (updateScheduled) { - updateScheduledInterface(true); - } + processDeletedMessages(markAsDeletedMessages, channelId); } else if (id == NotificationCenter.messageReceivedByServer) { Boolean scheduled = (Boolean) args[6]; - if (scheduled != inScheduleMode) { + if (scheduled != (chatMode == MODE_SCHEDULED)) { return; } Integer msgId = (Integer) args[0]; @@ -12517,10 +12447,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ArrayList messArr = new ArrayList<>(); messArr.add(obj); if (currentEncryptedChat == null) { - getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, inScheduleMode, null); + getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode == MODE_SCHEDULED, null); } if (chatAdapter != null) { - chatAdapter.updateRowWithMessageObject(obj, true); + chatAdapter.updateRowWithMessageObject(obj, false); } if (chatLayoutManager != null) { if (mediaUpdated && chatLayoutManager.findFirstVisibleItemPosition() == 0) { @@ -12535,7 +12465,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (obj != null) { obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; if (chatAdapter != null) { - chatAdapter.updateRowWithMessageObject(obj, true); + chatAdapter.updateRowWithMessageObject(obj, false); } } } else if (id == NotificationCenter.messageSendError) { @@ -12585,16 +12515,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionsAdapter.setChatInfo(chatInfo); } if (!isThreadChat()) { - if (args[3] instanceof MessageObject) { - pinnedMessageObject = (MessageObject) args[3]; - updatePinnedMessageView(false); - } else { - updatePinnedMessageView(true); - } if (avatarContainer != null) { avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); } + if (!loadingPinnedMessagesList && !pinnedMessageIds.isEmpty() && chatInfo.pinned_msg_id > pinnedMessageIds.get(0)) { + getMediaDataController().loadPinnedMessages(dialog_id, 0, chatInfo.pinned_msg_id); + loadingPinnedMessagesList = true; + } } if (chatInfo instanceof TLRPC.TL_chatFull) { hasBotsCommands = false; @@ -12642,7 +12570,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionsAdapter != null) { mentionsAdapter.setBotsCount(botsCount); } - if (!inScheduleMode && ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { + if (chatMode == 0 && ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; if (chatAdapter != null) { @@ -12716,9 +12644,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (obj.messageOwner.date - 1 <= date) { obj.setIsRead(); + if (chatAdapter != null) { + chatAdapter.invalidateRowWithMessageObject(obj); + } } } - updateVisibleRows(); } } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; @@ -13086,12 +13016,131 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkWaitingForReplies(); } updateReplyMessageHeader(true); - } else if (id == NotificationCenter.pinnedMessageDidLoad) { - MessageObject message = (MessageObject) args[0]; - if (message.getDialogId() == dialog_id && (chatInfo != null && chatInfo.pinned_msg_id == message.getId() || userInfo != null && userInfo.pinned_msg_id == message.getId())) { - pinnedMessageObject = message; - loadingPinnedMessage = 0; - updatePinnedMessageView(true); + } else if (id == NotificationCenter.didLoadPinnedMessages) { + long did = (Long) args[0]; + if (did == dialog_id) { + ArrayList ids = (ArrayList) args[1]; + boolean pin = (Boolean) args[2]; + ArrayList arrayList = (ArrayList) args[3]; + HashMap dict = null; + if (ids != null) { + HashMap replaceObjects = (HashMap) args[4]; + int maxId = (Integer) args[5]; + int totalPinnedCount = (Integer) args[6]; + boolean endReached = (Boolean) args[7]; + HashMap oldPinned = new HashMap<>(pinnedMessageObjects); + if (replaceObjects != null) { + loadingPinnedMessagesList = false; + if (maxId == 0) { + pinnedMessageIds.clear(); + pinnedMessageObjects.clear(); + } + totalPinnedMessagesCount = totalPinnedCount; + pinnedEndReached = endReached; + } + boolean updated = false; + if (arrayList != null) { + getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id, false, null); + } + for (int a = 0, N = ids.size(); a < N; a++) { + Integer mid = ids.get(a); + if (pin) { + if (pinnedMessageObjects.containsKey(mid)) { + continue; + } + pinnedMessageIds.add(mid); + MessageObject object = oldPinned.get(mid); + if (object == null) { + object = messagesDict[0].get(mid); + } + if (object == null && arrayList != null) { + if (dict == null) { + dict = new HashMap<>(); + for (int b = 0, N2 = arrayList.size(); b < N2; b++) { + MessageObject obj = arrayList.get(b); + if (obj != null) { + dict.put(obj.getId(), obj); + } + } + } + object = dict.get(mid); + } + if (object == null && replaceObjects != null) { + object = replaceObjects.get(mid); + } + pinnedMessageObjects.put(mid, object); + if (replaceObjects == null) { + totalPinnedMessagesCount++; + } + } else { + if (!pinnedMessageObjects.containsKey(mid)) { + continue; + } + pinnedMessageObjects.remove(mid); + pinnedMessageIds.remove(mid); + if (replaceObjects == null) { + totalPinnedMessagesCount--; + } + } + loadedPinnedMessagesCount = pinnedMessageIds.size(); + if (chatAdapter != null) { + MessageObject obj = messagesDict[0].get(mid); + if (obj != null) { + if (obj.hasValidGroupId()) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(obj.getGroupId()); + if (groupedMessages != null) { + int index = messages.indexOf(groupedMessages.messages.get(groupedMessages.messages.size() - 1)); + if (index >= 0) { + chatAdapter.notifyItemRangeChanged(index, groupedMessages.messages.size()); + } + } + } else { + chatAdapter.updateRowWithMessageObject(obj, false); + } + } + } + updated = true; + } + if (updated) { + if (chatMode == MODE_PINNED && avatarContainer != null) { + avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); + } + Collections.sort(pinnedMessageIds, (o1, o2) -> o2.compareTo(o1)); + if (pinnedMessageIds.isEmpty()) { + hidePinnedMessageView(true); + } else { + updateMessagesVisiblePart(false); + } + } + if (chatMode == MODE_PINNED) { + if (pin) { + if (arrayList != null) { + processNewMessages(arrayList); + } + } else { + processDeletedMessages(ids, ChatObject.isChannel(currentChat) ? currentChat.id : 0); + } + } + } else { + if (pin) { + for (int a = 0, N = arrayList.size(); a < N; a++) { + MessageObject message = arrayList.get(a); + if (pinnedMessageObjects.containsKey(message.getId())) { + pinnedMessageObjects.put(message.getId(), message); + } + loadingPinnedMessages.remove(message.getId()); + } + getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id, false, null); + updateMessagesVisiblePart(false); + } else { + pinnedMessageIds.clear(); + pinnedMessageObjects.clear(); + currentPinnedMessageId = 0; + loadedPinnedMessagesCount = 0; + totalPinnedMessagesCount = 0; + hidePinnedMessageView(true); + } + } } } else if (id == NotificationCenter.didReceivedWebpages) { ArrayList arrayList = (ArrayList) args[0]; @@ -13129,7 +13178,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.messagesReadContent) { ArrayList arrayList = (ArrayList) args[0]; - boolean updated = false; int currentChannelId = ChatObject.isChannel(currentChat) ? currentChat.id : 0; for (int a = 0; a < arrayList.size(); a++) { long mid = arrayList.get(a); @@ -13143,7 +13191,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject currentMessage = messagesDict[0].get((int) mid); if (currentMessage != null) { currentMessage.setContentIsRead(); - updated = true; if (currentMessage.messageOwner.mentioned) { newMentionsCount--; if (newMentionsCount <= 0) { @@ -13156,11 +13203,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + if (chatAdapter != null) { + chatAdapter.invalidateRowWithMessageObject(currentMessage); + } } } - if (updated) { - updateVisibleRows(); - } } else if (id == NotificationCenter.botInfoDidLoad) { int guid = (Integer) args[1]; if (classGuid == guid) { @@ -13277,7 +13324,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newGroups.put(groupedMessages.groupId, groupedMessages); } } - updated = true; + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(messageObject, false); + } } } } @@ -13291,7 +13340,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.inScheduleMode == inScheduleMode) { + if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode()) { hasChatInBack = true; break; } @@ -13335,6 +13384,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); + for (int b = 0, N2 = groupedMessages.messages.size(); b < N2; b++) { + groupedMessages.messages.get(b).animateComments = true; + } } } else if (chatAdapter != null) { int row = messages.indexOf(messageObject); @@ -13344,6 +13396,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } updatedRows.add(row + chatAdapter.messagesStartRow); } + messageObject.animateComments = true; } updated = true; } @@ -13382,6 +13435,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (did == dialog_id) { applyDraftMaybe(true); } + } else if (id == NotificationCenter.pinnedInfoDidLoad) { + long did = (Long) args[0]; + if (did == dialog_id) { + ArrayList pinnedMessages = (ArrayList) args[1]; + if (chatMode == MODE_PINNED) { + pinnedMessageIds = new ArrayList<>(pinnedMessages); + pinnedMessageObjects = new HashMap<>((HashMap) args[2]); + } else { + pinnedMessageIds = pinnedMessages; + pinnedMessageObjects = (HashMap) args[2]; + } + + loadedPinnedMessagesCount = pinnedMessageIds.size(); + totalPinnedMessagesCount = (Integer) args[3]; + pinnedEndReached = (Boolean) args[4]; + + getMediaDataController().loadReplyMessagesForMessages(new ArrayList<>(pinnedMessageObjects.values()), dialog_id, false, null); + + if (!loadingPinnedMessagesList && totalPinnedMessagesCount == 0 && !pinnedEndReached) { + getMediaDataController().loadPinnedMessages(dialog_id, 0, pinnedMessageIds.isEmpty() ? 0 : pinnedMessageIds.get(0)); + loadingPinnedMessagesList = true; + } + } } else if (id == NotificationCenter.userInfoDidLoad) { Integer uid = (Integer) args[0]; if (currentUser != null && currentUser.id == uid) { @@ -13399,11 +13475,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not headerItem.hideSubItem(video_call); } } - if (args[2] instanceof MessageObject) { - pinnedMessageObject = (MessageObject) args[2]; - updatePinnedMessageView(false); - } else { - updatePinnedMessageView(true); + if (!loadingPinnedMessagesList && !pinnedMessageIds.isEmpty() && userInfo.pinned_msg_id > pinnedMessageIds.get(0)) { + getMediaDataController().loadPinnedMessages(dialog_id, 0, userInfo.pinned_msg_id); + loadingPinnedMessagesList = true; } } } else if (id == NotificationCenter.didSetNewWallpapper) { @@ -13562,10 +13636,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not idsToRemove = new ArrayList<>(); } idsToRemove.add(waitingForReplies.keyAt(a)); - if (object.replyMessageObject.messageOwner.fwd_from != null && MessageObject.getPeerId(object.replyMessageObject.messageOwner.fwd_from.saved_from_peer) == dialog_id && object.replyMessageObject.messageOwner.fwd_from.channel_post != 0) { + if (!(object.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) && object.replyMessageObject.messageOwner.fwd_from != null && MessageObject.getPeerId(object.replyMessageObject.messageOwner.fwd_from.saved_from_peer) == dialog_id && object.replyMessageObject.messageOwner.fwd_from.channel_post != 0) { MessageObject obj = messagesDict[0].get(object.replyMessageObject.messageOwner.fwd_from.channel_post); if (obj != null && obj.messageOwner.replies != null) { obj.messageOwner.replies.replies += 1; + obj.animateComments = true; TLRPC.Peer peer = object.messageOwner.from_id; if (peer == null) { peer = object.messageOwner.peer_id; @@ -13589,6 +13664,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); + for (int b = 0, N2 = groupedMessages.messages.size(); b < N2; b++) { + groupedMessages.messages.get(b).animateComments = true; + } } } else { int row = messages.indexOf(obj); @@ -13676,9 +13754,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (startLoadFromMessageIdSaved != 0) { startLoadFromMessageId = startLoadFromMessageIdSaved; startLoadFromMessageIdSaved = 0; - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } else { if (progressView != null) { @@ -13717,7 +13795,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (lower_part != 0) { if (lower_part > 0) { bundle.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { bundle.putInt("chat_id", -lower_part); } } else { @@ -13730,14 +13808,823 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } + private void processNewMessages(ArrayList arr) { + int currentUserId = getUserConfig().getClientUserId(); + boolean updateChat = false; + boolean hasFromMe = false; + + + if (chatListItemAniamtor != null) { + chatListItemAniamtor.setShouldAnimateEnterFromBottom(true); + } + + boolean notifiedSearch = false; + LongSparseArray scheduledGroupReplacement = null; + for (int a = 0; a < arr.size(); a++) { + MessageObject messageObject = arr.get(a); + int messageId = messageObject.getId(); + if (threadMessageId != 0) { + if (messageId > 0 && messageId <= (messageObject.isOut() ? threadMaxOutboxReadId : threadMaxInboxReadId)) { + messageObject.setIsRead(); + } + } + if (messageObject.isDice() && !messageObject.isForwarded()) { + messageObject.wasUnread = true; + } + if (chatMode == MODE_SCHEDULED && messageObject.hasValidGroupId() && messagesDict[0].indexOfKey(messageObject.getId()) >= 0) { + long groupId = messageObject.getGroupId(); + if (scheduledGroupReplacement == null) { + scheduledGroupReplacement = new LongSparseArray<>(); + } + Long localId = scheduledGroupReplacement.get(groupId); + if (localId == null) { + localId = Utilities.random.nextLong(); + scheduledGroupReplacement.put(groupId, localId); + } + messageObject.localGroupId = localId; + } + if (messageObject.isOut()) { + if (!notifiedSearch) { + notifiedSearch = true; + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); + } + if (currentChat != null && currentChat.slowmode_enabled && messageObject.isSent() && chatMode != MODE_SCHEDULED) { + if (chatInfo != null) { + int date = messageObject.messageOwner.date + chatInfo.slowmode_seconds; + int currentTime = getConnectionsManager().getCurrentTime(); + if (date > getConnectionsManager().getCurrentTime()) { + chatInfo.slowmode_next_send_date = Math.max(chatInfo.slowmode_next_send_date, Math.min(currentTime + chatInfo.slowmode_seconds, date)); + if (chatActivityEnterView != null) { + chatActivityEnterView.setSlowModeTimer(chatInfo.slowmode_next_send_date); + } + } + } + getMessagesController().loadFullChat(currentChat.id, 0, true); + } + } + if (currentChat != null) { + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || + messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser && messageObject.messageOwner.action.users.contains(currentUserId)) { + TLRPC.Chat newChat = getMessagesController().getChat(currentChat.id); + if (newChat != null) { + currentChat = newChat; + checkActionBarMenu(); + updateBottomOverlay(); + if (avatarContainer != null) { + avatarContainer.updateSubtitle(true); + } + } + } + } else if (inlineReturn != 0) { + if (messageObject.messageOwner.reply_markup != null) { + for (int b = 0; b < messageObject.messageOwner.reply_markup.rows.size(); b++) { + TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(b); + for (int c = 0; c < row.buttons.size(); c++) { + TLRPC.KeyboardButton button = row.buttons.get(c); + if (button instanceof TLRPC.TL_keyboardButtonSwitchInline) { + processSwitchButton((TLRPC.TL_keyboardButtonSwitchInline) button); + break; + } + } + } + } + } + if (messageObject.getReplyMsgId() != 0 && messageObject.replyMessageObject == null) { + messageObject.replyMessageObject = messagesDict[0].get(messageObject.getReplyMsgId()); + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { + messageObject.generatePinMessageText(null, null); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { + messageObject.generateGameMessageText(null); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { + messageObject.generatePaymentSentMessageText(null); + } + if (messageObject.isMegagroup() && messageObject.replyMessageObject != null && messageObject.replyMessageObject.messageOwner != null) { + messageObject.replyMessageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + } + } + + if (chatMode == MODE_SCHEDULED && !arr.isEmpty()) { + replaceMessageObjects(arr, 0, true); + } + + boolean needMoveScrollToLastMessage = false; + + boolean reloadMegagroup = false; + if (!forwardEndReached[0]) { + int currentMaxDate = Integer.MIN_VALUE; + int currentMinMsgId = Integer.MIN_VALUE; + if (currentEncryptedChat != null) { + currentMinMsgId = Integer.MAX_VALUE; + } + + for (int a = 0; a < arr.size(); a++) { + MessageObject obj = arr.get(a); + if (threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { + continue; + } + int messageId = obj.getId(); + + if (obj.isOut() && waitingForSendingMessageLoad) { + waitingForSendingMessageLoad = false; + chatActivityEnterView.hideTopView(true); + if (changeBoundAnimator != null) { + changeBoundAnimator.start(); + } + } + + if (chatMode != MODE_SCHEDULED && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { + obj.setIsRead(); + } + TLRPC.MessageAction action = obj.messageOwner.action; + if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { + avatarContainer.setTime(((TLRPC.TL_decryptedMessageActionSetMessageTTL) action.encryptedAction).ttl_seconds); + } + if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { + migrateToNewChat(obj); + return; + } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { + reloadMegagroup = true; + } + if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && chatMode != MODE_SCHEDULED) { + needAnimateToMessage = obj; + } + if (obj.isOut() && obj.wasJustSent) { + scrollToLastMessage(); + return; + } + if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { + continue; + } + if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { + continue; + } + if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { + continue; + } + if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { + continue; + } + if (threadMessageObject != null && obj.isReply() && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { + int mid = obj.getReplyAnyMsgId(); + if (threadMessageObject.getId() == mid) { + threadMessageObject.messageOwner.replies.replies++; + } + } + addToPolls(obj, null); + obj.checkLayout(); + currentMaxDate = Math.max(currentMaxDate, obj.messageOwner.date); + if (messageId > 0) { + currentMinMsgId = Math.max(messageId, currentMinMsgId); + last_message_id = Math.max(last_message_id, messageId); + } else if (currentEncryptedChat != null) { + currentMinMsgId = Math.min(messageId, currentMinMsgId); + last_message_id = Math.min(last_message_id, messageId); + } + + if (threadMessageId == 0) { + if (obj.messageOwner.mentioned && obj.isContentUnread()) { + newMentionsCount++; + } + newUnreadMessageCount++; + } + if (obj.type == 10 || obj.type == 11) { + updateChat = true; + } + } + if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { + pagedownButtonCounter.setVisibility(View.VISIBLE); + if (prevSetUnreadCount != newUnreadMessageCount) { + prevSetUnreadCount = newUnreadMessageCount; + pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount)); + } + } + if (newMentionsCount != 0 && mentiondownButtonCounter != null) { + mentiondownButtonCounter.setVisibility(View.VISIBLE); + mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); + showMentionDownButton(true, true); + } + + updateVisibleRows(); + } else { + LongSparseArray newGroups = null; + HashMap> webpagesToReload = null; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("received new messages " + arr.size() + " in dialog " + dialog_id); + } + for (int a = 0; a < arr.size(); a++) { + MessageObject obj = arr.get(a); + if (obj.scheduled != (chatMode == MODE_SCHEDULED) || threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { + continue; + } + int placeToPaste = -1; + int messageId = obj.getId(); + if (chatMode == MODE_SCHEDULED && messagesDict[0].indexOfKey(messageId) >= 0) { + MessageObject removed = messagesDict[0].get(messageId); + messagesDict[0].remove(messageId); + if (removed != null) { + int index = messages.indexOf(removed); + messages.remove(index); + ArrayList dayArr = messagesByDays.get(removed.dateKey); + dayArr.remove(removed); + if (dayArr.isEmpty()) { + messagesByDays.remove(removed.dateKey); + if (index >= 0 && index < messages.size()) { + messages.remove(index); + } + } + if (removed.hasValidGroupId()) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); + groupedMessages.messages.remove(removed); + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + } + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(false); + } + } + } + if (isSecretChat()) { + checkSecretMessageForLocation(obj); + } + if (chatMode != MODE_SCHEDULED && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { + obj.setIsRead(); + } + TLRPC.MessageAction action = obj.messageOwner.action; + if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { + avatarContainer.setTime(((TLRPC.TL_decryptedMessageActionSetMessageTTL) action.encryptedAction).ttl_seconds); + } + if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { + continue; + } + if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { + continue; + } + if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { + continue; + } + if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { + continue; + } + if (threadMessageObject != null && threadMessageObject.messageOwner.replies != null && obj.isReply() && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { + int mid = obj.getReplyAnyMsgId(); + if (threadMessageObject.getId() == mid) { + threadMessageObject.messageOwner.replies.replies++; + } + } + addToPolls(obj, null); + if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && chatMode != MODE_SCHEDULED) { + animatingMessageObjects.add(obj); + } + + MessageObject.GroupedMessages groupedMessages; + if (obj.hasValidGroupId()) { + groupedMessages = groupedMessagesMap.get(obj.getGroupId()); + if (groupedMessages == null) { + groupedMessages = new MessageObject.GroupedMessages(); + groupedMessages.groupId = obj.getGroupId(); + groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); + } + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + groupedMessages.messages.add(obj); + } else { + groupedMessages = null; + } + + if (groupedMessages != null) { + int size = groupedMessages.messages.size(); + MessageObject messageObject = size > 1 ? groupedMessages.messages.get(groupedMessages.messages.size() - 2) : null; + if (messageObject != null) { + placeToPaste = messages.indexOf(messageObject); + } + } + + if (placeToPaste == -1) { + if (!obj.scheduled && obj.messageOwner.id < 0 || messages.isEmpty()) { + placeToPaste = 0; + } else { + int size = messages.size(); + for (int b = 0; b < size; b++) { + MessageObject lastMessage = messages.get(b); + if (lastMessage.type >= 0 && lastMessage.messageOwner.date > 0) { + if (chatMode != MODE_SCHEDULED && lastMessage.messageOwner.id > 0 && obj.messageOwner.id > 0 && lastMessage.messageOwner.id < obj.messageOwner.id || lastMessage.messageOwner.date <= obj.messageOwner.date) { + MessageObject.GroupedMessages lastGroupedMessages; + if (lastMessage.getGroupId() != 0) { + lastGroupedMessages = groupedMessagesMap.get(lastMessage.getGroupId()); + if (lastGroupedMessages != null && lastGroupedMessages.messages.size() == 0) { + lastGroupedMessages = null; + } + } else { + lastGroupedMessages = null; + } + if (lastGroupedMessages == null) { + placeToPaste = b; + } else { + placeToPaste = messages.indexOf(lastGroupedMessages.messages.get(lastGroupedMessages.messages.size() - 1)); + } + break; + } + } + } + if (placeToPaste == -1 || placeToPaste > messages.size()) { + placeToPaste = messages.size(); + } + } + } + if (currentEncryptedChat != null && obj.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && obj.messageOwner.media.webpage instanceof TLRPC.TL_webPageUrlPending) { + if (webpagesToReload == null) { + webpagesToReload = new HashMap<>(); + } + ArrayList arrayList = webpagesToReload.get(obj.messageOwner.media.webpage.url); + if (arrayList == null) { + arrayList = new ArrayList<>(); + webpagesToReload.put(obj.messageOwner.media.webpage.url, arrayList); + } + arrayList.add(obj); + } + obj.checkLayout(); + if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { + migrateToNewChat(obj); + if (newGroups != null) { + for (int b = 0; b < newGroups.size(); b++) { + newGroups.valueAt(b).calculate(); + } + } + return; + } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { + reloadMegagroup = true; + } + if (minDate[0] == 0 || obj.messageOwner.date < minDate[0]) { + minDate[0] = obj.messageOwner.date; + } + + if (obj.isOut() && !obj.messageOwner.from_scheduled) { + removeUnreadPlane(true); + hideDistanceView(); + hasFromMe = true; + } + + if (messageId > 0) { + maxMessageId[0] = Math.min(messageId, maxMessageId[0]); + minMessageId[0] = Math.max(messageId, minMessageId[0]); + } else if (currentEncryptedChat != null) { + maxMessageId[0] = Math.max(messageId, maxMessageId[0]); + minMessageId[0] = Math.min(messageId, minMessageId[0]); + } + maxDate[0] = Math.max(maxDate[0], obj.messageOwner.date); + messagesDict[0].put(messageId, obj); + ArrayList dayArray = messagesByDays.get(obj.dateKey); + if (placeToPaste > messages.size()) { + placeToPaste = messages.size(); + } + if (dayArray == null) { + dayArray = new ArrayList<>(); + messagesByDays.put(obj.dateKey, dayArray); + TLRPC.Message dateMsg = new TLRPC.TL_message(); + if (chatMode == MODE_SCHEDULED) { + if (obj.messageOwner.date == 0x7ffffffe) { + dateMsg.message = LocaleController.getString("MessageScheduledUntilOnline", R.string.MessageScheduledUntilOnline); + } else { + dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); + } + } else { + dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); + } + dateMsg.id = 0; + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 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 = lastStableId++; + messages.add(placeToPaste, dateObj); + if (chatAdapter != null) { + chatAdapter.notifyItemInserted(placeToPaste); + } + } + if (!(obj.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) && (!obj.isOut() || obj.messageOwner.from_scheduled)) { + if (paused && placeToPaste == 0) { + if (!scrollToTopUnReadOnResume && unreadMessageObject != null) { + removeMessageObject(unreadMessageObject); + unreadMessageObject = null; + } + if (unreadMessageObject == null) { + TLRPC.Message dateMsg = new TLRPC.TL_message(); + dateMsg.message = ""; + dateMsg.id = 0; + MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); + dateObj.type = 6; + dateObj.contentType = 2; + dateObj.stableId = lastStableId++; + messages.add(0, dateObj); + if (chatAdapter != null) { + chatAdapter.notifyItemInserted(0); + } + unreadMessageObject = dateObj; + scrollToMessage = unreadMessageObject; + scrollToMessagePosition = -10000; + scrollToTopUnReadOnResume = true; + } + } + } + + dayArray.add(0, obj); + + if (chatAdapter != null && placeToPaste >= 0 && placeToPaste < messages.size()) { + MessageObject prevMessage = messages.get(placeToPaste); + if (prevMessage.hasValidGroupId() && prevMessage.getGroupId() != obj.getGroupId()) { + MessageObject.GroupedMessages group = groupedMessagesMap.get(prevMessage.getGroupId()); + if (group != null && group.messages.size() > 1) { + int size = group.messages.size(); + chatAdapter.notifyItemRangeChanged(1, size - 1); + } + } + } + obj.stableId = lastStableId++; + messages.add(placeToPaste, obj); + if (placeToPaste == 0) { + needMoveScrollToLastMessage = true; + } + if (chatAdapter != null) { + chatAdapter.notifyItemChanged(placeToPaste); + chatAdapter.notifyItemInserted(placeToPaste); + } + if (obj.isOut() && waitingForSendingMessageLoad) { + waitingForSendingMessageLoad = false; + chatActivityEnterView.hideTopView(true); + if (changeBoundAnimator != null) { + changeBoundAnimator.start(); + } + } + if (threadMessageId == 0) { + if (!obj.isOut() && obj.messageOwner.mentioned && obj.isContentUnread()) { + newMentionsCount++; + } + newUnreadMessageCount++; + } + if (obj.type == 10 || obj.type == 11) { + updateChat = true; + } + } + if (webpagesToReload != null) { + getMessagesController().reloadWebPages(dialog_id, webpagesToReload, chatMode == MODE_SCHEDULED); + } + if (newGroups != null) { + for (int a = 0; a < newGroups.size(); a++) { + MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); + int oldCount = groupedMessages.posArray.size(); + groupedMessages.calculate(); + int newCount = groupedMessages.posArray.size(); + if (newCount - oldCount > 0 && chatAdapter != null) { + int index = messages.indexOf(groupedMessages.messages.get(groupedMessages.messages.size() - 1)); + if (index >= 0) { + chatAdapter.notifyItemRangeChanged(index, newCount); + } + } + } + } + + showProgressView(false); + if (chatAdapter == null) { + scrollToTopOnResume = true; + } + + if (chatListView != null && chatAdapter != null) { + int lastVisible = chatLayoutManager.findFirstVisibleItemPosition(); + if (lastVisible == RecyclerView.NO_POSITION) { + lastVisible = 0; + } + View child = chatLayoutManager.findViewByPosition(lastVisible); + int diff; + if (child != null) { + diff = child.getBottom() - chatListView.getMeasuredHeight(); + } else { + diff = 0; + } + if (lastVisible == 0 && diff <= AndroidUtilities.dp(5) || hasFromMe) { + newUnreadMessageCount = 0; + if (!firstLoading && chatMode != MODE_SCHEDULED) { + if (paused) { + scrollToTopOnResume = true; + } else { + forceScrollToTop = true; + moveScrollToLastMessage(); + } + } + } else { + if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { + pagedownButtonCounter.setVisibility(View.VISIBLE); + if (prevSetUnreadCount != newUnreadMessageCount) { + prevSetUnreadCount = newUnreadMessageCount; + pagedownButtonCounter.setText(String.format("%d", newUnreadMessageCount)); + } + } + canShowPagedownButton = true; + updatePagedownButtonVisibility(true); + } + if (newMentionsCount != 0 && mentiondownButtonCounter != null) { + mentiondownButtonCounter.setVisibility(View.VISIBLE); + mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); + showMentionDownButton(true, true); + } + } else { + scrollToTopOnResume = true; + } + } + if (chatMode == MODE_SCHEDULED && !arr.isEmpty()) { + MessageObject messageObject = arr.get(0); + int mid = messageObject.getId(); + if (mid < 0) { + if (chatListItemAniamtor != null) { + chatListItemAniamtor.setShouldAnimateEnterFromBottom(needMoveScrollToLastMessage); + } + if (needMoveScrollToLastMessage) { + moveScrollToLastMessage(); + } else { + int index = messages.indexOf(messageObject); + if (chatLayoutManager != null && index > 0 && (chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index) != null || chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index - 1) != null)) { + chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(messageObject), getScrollOffsetForMessage(messageObject), false); + } else { + AndroidUtilities.runOnUIThread(() -> scrollToMessageId(mid, 0, false, 0, true)); + } + } + + } + } + if (!messages.isEmpty() && botUser != null && botUser.length() == 0) { + botUser = null; + updateBottomOverlay(); + } + if (updateChat) { + updateTitle(); + checkAndUpdateAvatar(); + } + if (reloadMegagroup) { + getMessagesController().loadFullChat(currentChat.id, 0, true); + } + checkWaitingForReplies(); + updateReplyMessageHeader(true); + } + + private void processDeletedMessages(ArrayList markAsDeletedMessages, int channelId) { + ArrayList removedIndexes = new ArrayList<>(); + int loadIndex = 0; + if (ChatObject.isChannel(currentChat)) { + if (channelId == 0 && mergeDialogId != 0) { + loadIndex = 1; + } else if (channelId == currentChat.id) { + loadIndex = 0; + } else { + return; + } + } else if (channelId != 0) { + return; + } + boolean updated = false; + LongSparseArray newGroups = null; + LongSparseArray newGroupsSizes = null; + int size = markAsDeletedMessages.size(); + boolean updatedSelected = false; + boolean updatedSelectedLast = false; + boolean updateScheduled = false; + boolean hasChatInBack = false; + boolean updatedReplies = false; + + if (threadMessageObject != null && parentLayout != null) { + for (int a = 0, N = parentLayout.fragmentsStack.size() - 1; a < N; a++) { + BaseFragment fragment = parentLayout.fragmentsStack.get(a); + if (fragment != this && fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode()) { + hasChatInBack = true; + break; + } + } + } + } + + int commentsDeleted = 0; + for (int a = 0; a < size; a++) { + Integer mid = markAsDeletedMessages.get(a); + MessageObject obj = messagesDict[loadIndex].get(mid); + if (loadIndex == 0 && pinnedMessageObjects.containsKey(mid)) { + pinnedMessageObjects.remove(mid); + pinnedMessageIds.remove(mid); + loadedPinnedMessagesCount = pinnedMessageIds.size(); + totalPinnedMessagesCount--; + if (totalPinnedMessagesCount < 0) { + totalPinnedMessagesCount = 0; + } + if (currentPinnedMessageId == mid) { + currentPinnedMessageId = 0; + } + } + if (obj != null) { + if (obj.messageOwner.reply_to != null && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { + int replyId = obj.getReplyAnyMsgId(); + if (threadMessageObject != null && threadMessageObject.getId() == replyId) { + if (!hasChatInBack && threadMessageObject.hasReplies()) { + threadMessageObject.messageOwner.replies.replies--; + } + if (replyOriginalMessageId != 0) { + commentsDeleted++; + } + updatedReplies = true; + } else { + MessageObject replyObject = messagesDict[loadIndex].get(replyId); + if (replyObject != null && replyObject.hasReplies()) { + replyObject.messageOwner.replies.replies--; + replyObject.viewsReloaded = false; + } + } + } + obj.deleted = true; + if (editingMessageObject == obj) { + hideFieldPanel(true); + } + int index = messages.indexOf(obj); + if (index != -1) { + if (obj.scheduled) { + scheduledMessagesCount--; + updateScheduled = true; + } + if (selectedMessagesIds[loadIndex].indexOfKey(mid) >= 0) { + updatedSelected = true; + addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); + } + MessageObject removed = messages.remove(index); + if (chatAdapter != null) { + removedIndexes.add(chatAdapter.messagesStartRow + index); + } + if (removed.getGroupId() != 0) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); + if (groupedMessages != null) { + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + newGroupsSizes = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + if (newGroupsSizes.get(groupedMessages.groupId) == null) { + newGroupsSizes.put(groupedMessages.groupId, groupedMessages.messages.size()); + } + groupedMessages.messages.remove(obj); + } + } + messagesDict[loadIndex].remove(mid); + ArrayList dayArr = messagesByDays.get(obj.dateKey); + if (dayArr != null) { + dayArr.remove(obj); + if (dayArr.isEmpty()) { + messagesByDays.remove(obj.dateKey); + if (index >= 0 && index < messages.size()) { + messages.remove(index); + if (chatAdapter != null) { + removedIndexes.add(chatAdapter.messagesStartRow + index); + } + } + } + } + updated = true; + } + } + } + if (updatedReplies) { + updateReplyMessageHeader(true); + } + if (commentsDeleted != 0) { + getNotificationCenter().postNotificationName(NotificationCenter.changeRepliesCounter, replyOriginalChat.id, replyOriginalMessageId, -commentsDeleted); + getMessagesStorage().updateRepliesCount(replyOriginalChat.id, replyOriginalMessageId, null, 0, -commentsDeleted); + } + if (updatedSelected) { + if (!updatedSelectedLast) { + addToSelectedMessages(null, false, true); + } + updateActionModeTitle(); + } + if (newGroups != null) { + for (int a = 0; a < newGroups.size(); a++) { + MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); + if (chatListItemAniamtor != null) { + if (groupedMessages.messages.size() == 1) { + chatListItemAniamtor.groupWillTransformToSingleMessage(groupedMessages); + } else { + chatListItemAniamtor.groupWillChanged(groupedMessages); + } + } + + if (groupedMessages.messages.isEmpty()) { + groupedMessagesMap.remove(groupedMessages.groupId); + } else { + groupedMessages.calculate(); + MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); + int index = messages.indexOf(messageObject); + if (index >= 0) { + if (chatAdapter != null) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); + } + } + } + } + } + if (messages.isEmpty()) { + if (!endReached[0] && !loading) { + showProgressView(false); + if (chatListView != null) { + chatListView.setEmptyView(null); + } + if (currentEncryptedChat == null) { + maxMessageId[0] = maxMessageId[1] = Integer.MAX_VALUE; + minMessageId[0] = minMessageId[1] = Integer.MIN_VALUE; + } else { + maxMessageId[0] = maxMessageId[1] = Integer.MIN_VALUE; + minMessageId[0] = minMessageId[1] = Integer.MAX_VALUE; + } + maxDate[0] = maxDate[1] = Integer.MIN_VALUE; + minDate[0] = minDate[1] = 0; + waitingForLoad.add(lastLoadIndex); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); + loading = true; + } else { + if (botButtons != null) { + botButtons = null; + if (chatActivityEnterView != null) { + chatActivityEnterView.setButtons(null, false); + } + } + if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { + botUser = ""; + updateBottomOverlay(); + } + } + canShowPagedownButton = false; + updatePagedownButtonVisibility(true); + showMentionDownButton(false, true); + } + if (updated) { + if (chatMode == MODE_PINNED) { + if (avatarContainer != null) { + avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); + } + } + if (chatAdapter != null) { + int prevLoadingUpRow = chatAdapter.loadingUpRow; + int prevLoadingDownRow = chatAdapter.loadingDownRow; + for (int a = 0, N = removedIndexes.size(); a < N; a++) { + chatAdapter.notifyItemRemoved(removedIndexes.get(a)); + } + if (!isThreadChat() || messages.size() <= 3) { + removeUnreadPlane(false); + } + if (messages.isEmpty()) { + if (prevLoadingUpRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } + if (prevLoadingDownRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } + } else { + chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, messages.size()); + } + } + updateVisibleRows(); + } else if (threadMessageId == 0) { + first_unread_id = 0; + last_message_id = 0; + createUnreadMessageAfterId = 0; + removeMessageObject(unreadMessageObject); + unreadMessageObject = null; + if (pagedownButtonCounter != null) { + pagedownButtonCounter.setVisibility(View.INVISIBLE); + } + } + if (updateScheduled) { + updateScheduledInterface(true); + } + } + private void replaceMessageObjects(ArrayList messageObjects, int loadIndex, boolean remove) { LongSparseArray newGroups = null; for (int a = 0; a < messageObjects.size(); a++) { MessageObject messageObject = messageObjects.get(a); + MessageObject pinnedOld = pinnedMessageObjects.get(messageObject.getId()); + if (pinnedOld != null) { + pinnedMessageObjects.put(messageObject.getId(), messageObject); + } MessageObject old = messagesDict[loadIndex].get(messageObject.getId()); - if (pinnedMessageObject != null && pinnedMessageObject.getId() == messageObject.getId()) { - pinnedMessageObject = messageObject; - updatePinnedMessageView(true); + if (pinnedMessageObjects.containsKey(messageObject.getId())) { + pinnedMessageObjects.put(messageObject.getId(), messageObject); + if (messageObject.getId() == currentPinnedMessageId) { + updatePinnedMessageView(true); + } } if (old == null || remove && old.messageOwner.date != messageObject.messageOwner.date) { continue; @@ -13785,7 +14672,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (old.getGroupId() != messageObject.getGroupId()) { groupedMessagesMap.put(messageObject.getGroupId(), groupedMessages); } - if (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty()) { + if (!messageObject.isMusic() && !messageObject.isDocument() && (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty())) { if (newGroups == null) { newGroups = new LongSparseArray<>(); } @@ -13835,7 +14722,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (dayArr.isEmpty()) { messagesByDays.remove(old.dateKey); 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); + } + } } } } @@ -14001,12 +14898,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onBecomeFullyHidden() { - if (undoView != null) { - undoView.hide(true, 0); - } - if (topUndoView != null) { - topUndoView.hide(true, 0); - } + hideUndoViews(); } @Override @@ -14041,15 +14933,43 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } transitionAnimationIndex = getNotificationCenter().setAnimationInProgress(transitionAnimationIndex, alowedNotifications); + if (chatActivityEnterView != null && contentView != null && chatActivityEnterView.getAdjustPanLayoutHelper() != null && !chatActivityEnterView.getAdjustPanLayoutHelper().animationInProgress()) { + fixedKeyboardHeight = contentView.getKeyboardHeight(); + } + } + + @Override + protected void onTransitionAnimationProgress(boolean isOpen, float progress) { + if (blurredView != null && blurredView.getVisibility() == View.VISIBLE) { + if (isOpen) { + blurredView.setAlpha(1.0f - progress); + } else { + blurredView.setAlpha(progress); + } + } } @Override public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { if (isOpen) { - fragmentOpened = true; + if (!fragmentOpened) { + fragmentOpened = true; + updateMessagesVisiblePart(false); + } + if (backward) { + if (showPinBulletin && pinBulletin != null) { + pinBulletin.show(); + showPinBulletin = false; + } + } } + fixedKeyboardHeight = -1; getNotificationCenter().onAnimationFinish(transitionAnimationIndex); if (isOpen) { + if (blurredView != null && blurredView.getVisibility() == View.VISIBLE) { + blurredView.setVisibility(View.GONE); + blurredView.setBackground(null); + } openAnimationEnded = true; if (Build.VERSION.SDK_INT >= 21) { createChatAttachView(); @@ -14076,7 +14996,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.inScheduleMode == inScheduleMode && chatActivity.threadMessageId == threadMessageId) { + if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode() && chatActivity.threadMessageId == threadMessageId) { fragment.removeSelfFromStack(); break; } @@ -14179,7 +15099,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_mono, 8, stringBuilder); - if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { + if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; @@ -14202,10 +15122,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateBottomOverlay() { - if (bottomOverlayChatText == null || inScheduleMode) { + if (bottomOverlayChatText == null || chatMode == MODE_SCHEDULED) { return; } - if (currentChat != null) { + if (chatMode == MODE_PINNED) { + boolean allowPin; + if (currentChat != null) { + allowPin = ChatObject.canPinMessages(currentChat); + } else { + if (userInfo != null) { + allowPin = userInfo.can_pin_message; + } else { + allowPin = false; + } + } + if (allowPin) { + bottomOverlayChatText.setTag(1); + bottomOverlayChatText.setText(LocaleController.getString("UnpinAllMessages", R.string.UnpinAllMessages)); + } else { + bottomOverlayChatText.setTag(null); + bottomOverlayChatText.setText(LocaleController.getString("HidePinnedMessages", R.string.HidePinnedMessages)); + } + showBottomOverlayProgress(false, false); + } else if (currentChat != null) { if (!isThreadChat()) { if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { if (ChatObject.isNotInChat(currentChat)) { @@ -14288,7 +15227,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not muteItem.setVisibility(View.VISIBLE); } } - if (currentChat != null && !isThreadChat() && (ChatObject.isNotInChat(currentChat) || !ChatObject.canWriteToChat(currentChat)) || + if (chatMode == MODE_PINNED || + currentChat != null && !isThreadChat() && (ChatObject.isNotInChat(currentChat) || !ChatObject.canWriteToChat(currentChat)) || currentUser != null && (UserObject.isDeleted(currentUser) || userBlocked || UserObject.isReplyUser(currentUser))) { if (chatActivityEnterView.isEditingMessage()) { chatActivityEnterView.setVisibility(View.VISIBLE); @@ -14438,6 +15378,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean hidePinnedMessageView(boolean animated) { if (pinnedMessageView.getTag() == null) { + for (int a = 0; a < pinnedNextAnimation.length; a++) { + if (pinnedNextAnimation[a] != null) { + pinnedNextAnimation[a].cancel(); + pinnedNextAnimation[a] = null; + } + } + setPinnedTextTranslationX = false; pinnedMessageView.setTag(1); if (pinnedMessageViewAnimator != null) { pinnedMessageViewAnimator.cancel(); @@ -14481,42 +15428,99 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updatePinnedMessageView(boolean animated) { - if (pinnedMessageView == null || inScheduleMode) { + updatePinnedMessageView(animated, 0); + } + + private void updatePinnedListButton(boolean animated) { + if (isThreadChat() || pinnedListButton == null) { + return; + } + boolean show = pinnedMessageIds.size() > 1; + boolean visible = pinnedListButton.getTag() != null; + if (show != visible) { + if (pinnedListAnimator != null) { + pinnedListAnimator.cancel(); + pinnedListAnimator = null; + } + if (animated) { + if (show) { + pinnedListButton.setVisibility(View.VISIBLE); + } else { + closePinned.setVisibility(View.VISIBLE); + } + pinnedListAnimator = new AnimatorSet(); + pinnedListAnimator.playTogether( + ObjectAnimator.ofFloat(pinnedListButton, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(pinnedListButton, View.SCALE_X, show ? 1.0f : 0.4f), + ObjectAnimator.ofFloat(pinnedListButton, View.SCALE_Y, show ? 1.0f : 0.4f), + ObjectAnimator.ofFloat(closePinned, View.ALPHA, show ? 0.0f : 1.0f), + ObjectAnimator.ofFloat(closePinned, View.SCALE_X, show ? 0.4f : 1.0f), + ObjectAnimator.ofFloat(closePinned, View.SCALE_Y, show ? 0.4f : 1.0f)); + pinnedListAnimator.setDuration(180); + pinnedListAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + pinnedListAnimator = null; + if (show) { + closePinned.setVisibility(View.INVISIBLE); + } else { + pinnedListButton.setVisibility(View.INVISIBLE); + } + } + }); + pinnedListAnimator.start(); + } else { + closePinned.setAlpha(show ? 0.0f : 1.0f); + closePinned.setScaleX(show ? 0.4f : 1.0f); + closePinned.setScaleY(show ? 0.4f : 1.0f); + closePinned.setVisibility(show ? View.INVISIBLE : View.VISIBLE); + pinnedListButton.setAlpha(show ? 1.0f : 0.0f); + pinnedListButton.setScaleX(show ? 1.0f : 0.4f); + pinnedListButton.setScaleY(show ? 1.0f : 0.4f); + pinnedListButton.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + pinnedListButton.setTag(show ? 1 : null); + } + if (pinnedLineView != null) { + if (isThreadChat()) { + pinnedLineView.set(0, 1, false); + } else { + int position = Collections.binarySearch(pinnedMessageIds, currentPinnedMessageId, Comparator.reverseOrder()); + pinnedLineView.set(pinnedMessageIds.size() - 1 - position, pinnedMessageIds.size(), animated); + } + } + } + + private void updatePinnedMessageView(boolean animated, int animateToNext) { + if (pinnedMessageView == null || chatMode != 0) { return; } int pinned_msg_id; boolean changed = false; + MessageObject pinnedMessageObject; if (isThreadChat()) { - if (!replyMessageVisible) { + if (!threadMessageVisible) { pinnedMessageObject = threadMessageObject; pinned_msg_id = threadMessageId; } else { pinnedMessageObject = null; pinned_msg_id = 0; } - } else if (chatInfo != null) { - if (pinnedMessageObject != null && chatInfo.pinned_msg_id != pinnedMessageObject.getId()) { - pinnedMessageObject = null; + } else if (currentPinnedMessageId != 0 && !pinnedMessageIds.isEmpty()) { + pinnedMessageObject = pinnedMessageObjects.get(currentPinnedMessageId); + if (pinnedMessageObject == null) { + pinnedMessageObject = messagesDict[0].get(currentPinnedMessageId); } - if (chatInfo.pinned_msg_id != 0 && pinnedMessageObject == null) { - pinnedMessageObject = messagesDict[0].get(chatInfo.pinned_msg_id); - } - pinned_msg_id = chatInfo.pinned_msg_id; - } else if (userInfo != null) { - if (pinnedMessageObject != null && userInfo.pinned_msg_id != pinnedMessageObject.getId()) { - pinnedMessageObject = null; - } - if (userInfo.pinned_msg_id != 0 && pinnedMessageObject == null) { - pinnedMessageObject = messagesDict[0].get(userInfo.pinned_msg_id); - } - pinned_msg_id = userInfo.pinned_msg_id; + pinned_msg_id = currentPinnedMessageId; } else { + pinnedMessageObject = null; pinned_msg_id = 0; } SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - if (threadMessageObject == null && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || pinned_msg_id == preferences.getInt("pin_" + dialog_id, 0)) || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { + if (threadMessageObject == null && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || !pinnedMessageIds.isEmpty() && pinnedMessageIds.get(0) == preferences.getInt("pin_" + dialog_id, 0)) || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { changed = hidePinnedMessageView(animated); } else { + updatePinnedListButton(animated); if (pinnedMessageObject != null) { if (pinnedMessageView.getTag() != null) { pinnedMessageView.setTag(null); @@ -14531,21 +15535,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int position = -1; @Override public void onAnimationUpdate(ValueAnimator animation) { - float translationY = (float) animation.getAnimatedValue(); - if (!isThreadChat() && !wasManualScroll && unreadMessageObject != null && chatListView != null) { - int msgIndex = position - chatAdapter.messagesStartRow; - if (msgIndex < 0 || msgIndex >= messages.size() || messages.get(msgIndex) != unreadMessageObject) { - position = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject); - } - if (position >= 0) { - View v = chatLayoutManager.findViewByPosition(position); - float top = pinnedMessageView.getBottom() + translationY - chatListView.getTop(); - if (v != null && top > v.getTop() + AndroidUtilities.dp(9)) { - chatListView.scrollBy(0, (int) (v.getTop() + AndroidUtilities.dp(9) - top)); - } - } - } - pinnedMessageEnterOffset = translationY; + pinnedMessageEnterOffset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); chatListView.invalidate(); } @@ -14573,15 +15563,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { pinnedMessageEnterOffset = 0; invalidateChatListViewTopPadding(); - chatListView.invalidate(); - if (firstLoading) { - updateChatListViewTopPadding(); - } pinnedMessageView.setVisibility(View.VISIBLE); } } - FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) pinnedMessageNameTextView.getLayoutParams(); - FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) pinnedMessageTextView.getLayoutParams(); + for (int a = 0; a < pinnedNextAnimation.length; a++) { + if (pinnedNextAnimation[a] != null) { + pinnedNextAnimation[a].cancel(); + pinnedNextAnimation[a] = null; + } + } + setPinnedTextTranslationX = false; + SimpleTextView nameTextView = pinnedNameTextView[animateToNext != 0 && loadedPinnedMessagesCount == 2 ? 1 : 0]; + SimpleTextView messageTextView = pinnedMessageTextView[animateToNext != 0 ? 1 : 0]; + FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) pinnedNameTextView[0].getLayoutParams(); + FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) pinnedNameTextView[1].getLayoutParams(); + FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) pinnedCounterTextView.getLayoutParams(); + FrameLayout.LayoutParams layoutParams4 = (FrameLayout.LayoutParams) pinnedMessageTextView[0].getLayoutParams(); + FrameLayout.LayoutParams layoutParams5 = (FrameLayout.LayoutParams) pinnedMessageTextView[1].getLayoutParams(); int cacheType = 1; int size = 0; @@ -14604,29 +15602,39 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (photoSize == thumbPhotoSize) { thumbPhotoSize = null; } - if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || pinnedMessageObject.isAnyKindOfSticker()) { - pinnedMessageImageView.setImageBitmap(null); + boolean noImage; + int prevMargin = layoutParams1.leftMargin; + if (noImage = (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || pinnedMessageObject.isAnyKindOfSticker() || pinnedMessageObject.isSecretMedia())) { pinnedImageLocation = null; pinnedImageLocationObject = null; - pinnedMessageImageView.setVisibility(View.INVISIBLE); - layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(18); + if (animateToNext == 0) { + pinnedMessageImageView[0].setImageBitmap(null); + pinnedMessageImageView[0].setVisibility(View.INVISIBLE); + } + layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = AndroidUtilities.dp(18); } else { if (pinnedMessageObject.isRoundVideo()) { - pinnedMessageImageView.setRoundRadius(AndroidUtilities.dp(16)); + pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(16)); } else { - pinnedMessageImageView.setRoundRadius(0); + pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(2)); } pinnedImageSize = size; pinnedImageCacheType = cacheType; pinnedImageLocation = photoSize; pinnedImageThumbLocation = thumbPhotoSize; pinnedImageLocationObject = photoSizeObject; - pinnedMessageImageView.setImage(ImageLocation.getForObject(pinnedImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, pinnedMessageObject); - pinnedMessageImageView.setVisibility(View.VISIBLE); - layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(55); + pinnedMessageImageView[1].setImage(ImageLocation.getForObject(pinnedImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, pinnedMessageObject); + pinnedMessageImageView[1].setVisibility(View.VISIBLE); + if (animateToNext != 0) { + pinnedMessageImageView[1].setAlpha(0.0f); + } + layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = AndroidUtilities.dp(55); } - pinnedMessageNameTextView.setLayoutParams(layoutParams1); - pinnedMessageTextView.setLayoutParams(layoutParams2); + pinnedNameTextView[0].setLayoutParams(layoutParams1); + pinnedNameTextView[1].setLayoutParams(layoutParams2); + pinnedCounterTextView.setLayoutParams(layoutParams3); + pinnedMessageTextView[0].setLayoutParams(layoutParams4); + pinnedMessageTextView[1].setLayoutParams(layoutParams5); if (threadMessageId != 0) { MessagesController messagesController = MessagesController.getInstance(currentAccount); @@ -14667,17 +15675,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chat = messagesController.getChat(threadMessageObject.messageOwner.peer_id.channel_id); } if (user != null) { - pinnedMessageNameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); } else if (chat != null) { - pinnedMessageNameTextView.setText(chat.title); + nameTextView.setText(chat.title); } - } else if (pinnedMessageObject.type == MessageObject.TYPE_POLL) { - pinnedMessageNameTextView.setText(LocaleController.getString("PinnedPoll", R.string.PinnedPoll)); } else { - pinnedMessageNameTextView.setText(LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); + if (currentPinnedMessageIndex[0] == 0 || loadedPinnedMessagesCount != 2) { + nameTextView.setText(LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); + } else { + nameTextView.setText(LocaleController.getString("PreviousPinnedMessage", R.string.PreviousPinnedMessage)); + } + if (currentPinnedMessageIndex[0] != 0) { + int total = getPinnedMessagesCount(); + pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), animated && pinnedCounterTextView.getTag() == null); + } } if (pinnedMessageObject.type == 14) { - pinnedMessageTextView.setText(String.format("%s - %s", pinnedMessageObject.getMusicAuthor(), pinnedMessageObject.getMusicTitle())); + messageTextView.setText(String.format("%s - %s", pinnedMessageObject.getMusicAuthor(), pinnedMessageObject.getMusicTitle())); } else if (pinnedMessageObject.type == MessageObject.TYPE_POLL) { TLRPC.TL_messageMediaPoll poll = (TLRPC.TL_messageMediaPoll) pinnedMessageObject.messageOwner.media; String mess = poll.poll.question; @@ -14685,31 +15699,300 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); - pinnedMessageTextView.setText(mess); + messageTextView.setText(mess); } else if (pinnedMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - pinnedMessageTextView.setText(Emoji.replaceEmoji(pinnedMessageObject.messageOwner.media.game.title, pinnedMessageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + messageTextView.setText(Emoji.replaceEmoji(pinnedMessageObject.messageOwner.media.game.title, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); } else if (!TextUtils.isEmpty(pinnedMessageObject.caption)) { String mess = pinnedMessageObject.caption.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); - pinnedMessageTextView.setText(Emoji.replaceEmoji(mess, pinnedMessageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + messageTextView.setText(Emoji.replaceEmoji(mess, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); } else if (pinnedMessageObject.messageText != null) { String mess = pinnedMessageObject.messageText.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); - pinnedMessageTextView.setText(Emoji.replaceEmoji(mess, pinnedMessageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + messageTextView.setText(Emoji.replaceEmoji(mess, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + } + if (animateToNext != 0) { + pinnedNextAnimation[0] = new AnimatorSet(); + pinnedNextAnimation[1] = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + ArrayList animators2 = new ArrayList<>(); + messageTextView.setVisibility(View.VISIBLE); + nameTextView.setVisibility(View.VISIBLE); + + if (loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0) { + if (pinnedCounterTextView.getTag() == null) { + animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.ALPHA, 1.0f, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_Y, 0.0f, -AndroidUtilities.dp(4))); + pinnedCounterTextView.setTag(1); + } + } else { + if (pinnedCounterTextView.getTag() != null) { + pinnedCounterTextView.setVisibility(View.VISIBLE); + pinnedCounterTextView.setAlpha(0.0f); + animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.ALPHA, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_Y, -AndroidUtilities.dp(4), 0)); + pinnedCounterTextView.setTag(null); + } + } + + if (loadedPinnedMessagesCount == 2 && !TextUtils.equals(nameTextView.getText(), pinnedNameTextView[0].getText())) { + nameTextView.setAlpha(0); + animators.add(ObjectAnimator.ofFloat(nameTextView, View.ALPHA, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.ALPHA, 1.0f, 0.0f)); + animators.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -4 : 4))); + } else { + if (nameTextView != pinnedNameTextView[0]) { + nameTextView.setAlpha(1.0f); + pinnedNameTextView[0].setAlpha(0.0f); + nameTextView.setTranslationY(0.0f); + pinnedNameTextView[0].setTranslationY(0.0f); + } else { + nameTextView.setAlpha(1.0f); + nameTextView.setTranslationY(0.0f); + pinnedNameTextView[1].setTranslationY(0.0f); + pinnedNameTextView[1].setAlpha(0.0f); + } + } + + boolean animateText; + if (!TextUtils.equals(messageTextView.getText(), pinnedMessageTextView[0].getText())) { + messageTextView.setAlpha(0); + animators.add(ObjectAnimator.ofFloat(messageTextView, View.ALPHA, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.ALPHA, 1.0f, 0.0f)); + if (animateText = forceScrollToFirst && loadedPinnedMessagesCount > 5) { + animators2.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, AndroidUtilities.dp(4), AndroidUtilities.dp(-2))); + } else { + animators.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); + } + animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -4 : 4))); + } else { + animateText = false; + messageTextView.setAlpha(1.0f); + pinnedMessageTextView[0].setAlpha(0.0f); + messageTextView.setTranslationY(0.0f); + pinnedMessageTextView[0].setTranslationY(0.0f); + } + + BackupImageView animateImage; + if (layoutParams1.leftMargin != prevMargin) { + animateImage = null; + setPinnedTextTranslationX = true; + int diff = prevMargin - layoutParams1.leftMargin; + animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.TRANSLATION_X, diff, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[1], View.TRANSLATION_X, diff, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_X, diff, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[1], View.TRANSLATION_X, diff, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_X, pinnedCounterTextViewX + diff, pinnedCounterTextViewX)); + if (diff > 0) { + pinnedMessageImageView[0].setAlpha(1f); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.ALPHA, 1.0f, 0.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.SCALE_X, 1.0f, 0.7f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.SCALE_Y, 1.0f, 0.7f)); + } else { + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.ALPHA, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.SCALE_X, 0.7f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.SCALE_Y, 0.7f, 1.0f)); + } + } else { + setPinnedTextTranslationX = false; + messageTextView.setTranslationX(0); + pinnedMessageTextView[0].setTranslationX(0); + nameTextView.setTranslationX(0); + pinnedNameTextView[0].setTranslationX(0); + pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); + pinnedMessageImageView[1].setAlpha(1.0f); + if (!noImage) { + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.ALPHA, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.ALPHA, 1.0f, 0.0f)); + if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { + animateImage = pinnedMessageImageView[1]; + animators2.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.TRANSLATION_Y, AndroidUtilities.dp(3), AndroidUtilities.dp(-2))); + } else { + animateImage = null; + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 3 : -3), 0.0f)); + } + animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -3 : 3))); + } else { + animateImage = null; + } + } + + pinnedNextAnimation[1].addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationCancel(Animator animation) { + pinnedNextAnimation[1] = null; + pinnedMessageImageView[1].setTranslationY(0); + } + + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(pinnedNextAnimation[1])) { + if (animateText || animateImage != null) { + pinnedNextAnimation[1] = new AnimatorSet(); + pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT); + pinnedNextAnimation[1].setDuration(180); + ArrayList animators1 = new ArrayList<>(); + if (animateText) { + animators1.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, 0.0f)); + } + if (animateImage != null) { + animators1.add(ObjectAnimator.ofFloat(animateImage, View.TRANSLATION_Y, 0.0f)); + } + pinnedNextAnimation[1].addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animateText) { + messageTextView.setTranslationY(0.0f); + } + if (animateImage != null) { + animateImage.setTranslationY(0.0f); + } + pinnedNextAnimation[1] = null; + } + }); + pinnedNextAnimation[1].playTogether(animators1); + pinnedNextAnimation[1].start(); + } else { + pinnedNextAnimation[1] = null; + } + } + } + }); + + pinnedNextAnimation[1].setDuration(180); + if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { + pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT); + } + pinnedNextAnimation[1].playTogether(animators2); + + pinnedNextAnimation[0].playTogether(animators); + pinnedNextAnimation[0].addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (pinnedCounterTextView.getTag() != null) { + pinnedCounterTextView.setVisibility(View.INVISIBLE); + int total = getPinnedMessagesCount(); + pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), false); + } else { + pinnedCounterTextView.setAlpha(1.0f); + } + pinnedCounterTextView.setTranslationY(0.0f); + pinnedMessageTextView[0].setTranslationX(0); + pinnedMessageTextView[1].setTranslationX(0); + pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); + if (!animateText) { + messageTextView.setTranslationY(0.0f); + } + nameTextView.setTranslationY(0.0f); + pinnedNameTextView[0].setTranslationX(0); + pinnedNameTextView[1].setTranslationX(0); + pinnedMessageImageView[1].setAlpha(1.0f); + pinnedMessageImageView[1].setScaleX(1f); + pinnedMessageImageView[1].setScaleY(1f); + pinnedMessageImageView[0].setAlpha(1.0f); + pinnedMessageImageView[0].setScaleX(1f); + pinnedMessageImageView[0].setScaleY(1f); + pinnedMessageTextView[1] = pinnedMessageTextView[0]; + pinnedMessageTextView[0] = messageTextView; + pinnedMessageTextView[1].setVisibility(View.INVISIBLE); + if (nameTextView != pinnedNameTextView[0]) { + pinnedNameTextView[1] = pinnedNameTextView[0]; + pinnedNameTextView[0] = nameTextView; + pinnedNameTextView[1].setVisibility(View.INVISIBLE); + } + if (noImage) { + pinnedMessageImageView[1].setImageBitmap(null); + pinnedMessageImageView[1].setVisibility(View.INVISIBLE); + } + BackupImageView backupImageView = pinnedMessageImageView[1]; + pinnedMessageImageView[1] = pinnedMessageImageView[0]; + pinnedMessageImageView[0] = backupImageView; + pinnedMessageImageView[1].setAlpha(1.0f); + pinnedMessageImageView[1].setScaleX(1f); + pinnedMessageImageView[1].setScaleY(1f); + pinnedMessageImageView[1].setVisibility(View.INVISIBLE); + + pinnedNextAnimation[0] = null; + setPinnedTextTranslationX = false; + } + }); + pinnedNextAnimation[0].setDuration(180); + if (!setPinnedTextTranslationX) { + pinnedNextAnimation[0].start(); + pinnedNextAnimation[1].start(); + } + } else { + if (loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0) { + if (pinnedCounterTextView.getTag() == null) { + pinnedCounterTextView.setAlpha(0.0f); + pinnedCounterTextView.setVisibility(View.INVISIBLE); + pinnedCounterTextView.setTag(1); + + } + } else { + if (pinnedCounterTextView.getTag() != null) { + pinnedCounterTextView.setVisibility(View.VISIBLE); + pinnedCounterTextView.setAlpha(1.0f); + pinnedCounterTextView.setTag(null); + } + } + pinnedCounterTextView.setTranslationY(0.0f); + pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); + + pinnedCounterTextView.setAlpha(loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0 ? 0.0f : 1.0f); + + messageTextView.setVisibility(View.VISIBLE); + messageTextView.setAlpha(1.0f); + messageTextView.setTranslationX(0); + messageTextView.setTranslationY(0); + nameTextView.setVisibility(View.VISIBLE); + nameTextView.setAlpha(1.0f); + nameTextView.setTranslationX(0); + nameTextView.setTranslationY(0); + pinnedMessageTextView[1].setVisibility(View.INVISIBLE); + pinnedMessageTextView[1].setTranslationX(0); + pinnedMessageTextView[1].setTranslationY(0); + pinnedNameTextView[1].setVisibility(View.INVISIBLE); + pinnedNameTextView[1].setTranslationX(0); + pinnedNameTextView[1].setTranslationY(0); + pinnedMessageImageView[0].setVisibility(View.INVISIBLE); + BackupImageView backupImageView = pinnedMessageImageView[1]; + pinnedMessageImageView[1] = pinnedMessageImageView[0]; + pinnedMessageImageView[0] = backupImageView; + pinnedMessageImageView[0].setAlpha(1.0f); + pinnedMessageImageView[0].setScaleX(1f); + pinnedMessageImageView[0].setScaleY(1f); + pinnedMessageImageView[0].setTranslationY(0); + pinnedMessageImageView[1].setAlpha(1.0f); + pinnedMessageImageView[1].setScaleX(1f); + pinnedMessageImageView[1].setScaleY(1f); + pinnedMessageImageView[1].setTranslationY(0); + } + if (isThreadChat()) { + pinnedLineView.set(0, 1, false); + } else { + int position = Collections.binarySearch(pinnedMessageIds, currentPinnedMessageId, Comparator.reverseOrder()); + pinnedLineView.set(pinnedMessageIds.size() - 1 - position, pinnedMessageIds.size(), animateToNext != 0); } } else { + pinnedCounterTextView.setVisibility(loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0 ? View.INVISIBLE : View.VISIBLE); + pinnedCounterTextView.setAlpha(loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0 ? 0.0f : 1.0f); pinnedImageLocation = null; pinnedImageLocationObject = null; changed = hidePinnedMessageView(animated); - if (loadingPinnedMessage != pinned_msg_id) { - loadingPinnedMessage = pinned_msg_id; - getMediaDataController().loadPinnedMessage(dialog_id, ChatObject.isChannel(currentChat) ? currentChat.id : 0, pinned_msg_id, true); + if (loadingPinnedMessages.indexOfKey(pinned_msg_id) < 0) { + loadingPinnedMessages.put(pinned_msg_id, true); + ArrayList ids = new ArrayList<>(); + ids.add(pinned_msg_id); + getMediaDataController().loadPinnedMessages(dialog_id, ChatObject.isChannel(currentChat) ? currentChat.id : 0, ids, true); } } } @@ -14719,7 +16002,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateTopPanel(boolean animated) { - if (topChatPanelView == null || inScheduleMode) { + if (topChatPanelView == null || chatMode != 0) { return; } @@ -14912,23 +16195,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkListViewPaddings(); } - private void checkListViewPaddingsInternal() { - if (chatLayoutManager == null) { - return; - } - try { - if (chatListViewPaddingTop != AndroidUtilities.dp(48) && (!isThreadChat() && pinnedMessageView != null && pinnedMessageView.getTag() == null || topChatPanelView != null && topChatPanelView.getTag() == null)) { - chatListViewPaddingTop = AndroidUtilities.dp(48); - invalidateChatListViewTopPadding(); - } else if (chatListViewPaddingTop != 0 && (isThreadChat() || pinnedMessageView == null || pinnedMessageView.getTag() != null) && (topChatPanelView == null || topChatPanelView.getTag() != null)) { - chatListViewPaddingTop = 0; - invalidateChatListViewTopPadding(); - } - } catch (Exception e) { - FileLog.e(e); - } - } - private void checkListViewPaddings() { if (!wasManualScroll && unreadMessageObject != null) { int pos = messages.indexOf(unreadMessageObject); @@ -14944,7 +16210,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } AndroidUtilities.runOnUIThread(checkPaddingsRunnable = () -> { checkPaddingsRunnable = null; - checkListViewPaddingsInternal(); + invalidateChatListViewTopPadding(); }); } } @@ -14977,7 +16243,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.setInPreviewMode(value); if (avatarContainer != null) { avatarContainer.setOccupyStatusBar(!value); - avatarContainer.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !value ? 56 : 0, 0, 40, 0)); + avatarContainer.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !value ? 56 : (chatMode == MODE_PINNED ? 10 : 0), 0, 40, 0)); } if (chatActivityEnterView != null) { chatActivityEnterView.setVisibility(!value ? View.VISIBLE : View.INVISIBLE); @@ -15030,6 +16296,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onResume() { super.onResume(); + if (parentLayout != null && !parentLayout.isInPreviewMode() && blurredView != null && blurredView.getVisibility() == View.VISIBLE) { + blurredView.setVisibility(View.GONE); + blurredView.setBackground(null); + } activityResumeTime = System.currentTimeMillis(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); @@ -15064,13 +16334,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, replyImageLocationObject), "50_50", ImageLocation.getForObject(replyImageThumbLocation, replyImageLocationObject), "50_50_b", null, replyImageSize, replyImageCacheType, replyingMessageObject); } if (pinnedImageLocation != null && pinnedMessageImageView != null) { - pinnedMessageImageView.setImage(ImageLocation.getForObject(pinnedImageLocation, pinnedImageLocationObject), "50_50", ImageLocation.getForObject(pinnedImageThumbLocation, pinnedImageLocationObject), "50_50_b", null, pinnedImageSize, pinnedImageCacheType, pinnedMessageObject); + MessageObject pinnedMessageObject = pinnedMessageObjects.get(currentPinnedMessageId); + pinnedMessageImageView[0].setImage(ImageLocation.getForObject(pinnedImageLocation, pinnedImageLocationObject), "50_50", ImageLocation.getForObject(pinnedImageThumbLocation, pinnedImageLocationObject), "50_50_b", null, pinnedImageSize, pinnedImageCacheType, pinnedMessageObject); } - if (!inScheduleMode) { + if (chatMode == 0) { getNotificationsController().setOpenedDialogId(dialog_id); } - getMessagesController().setLastVisibleDialogId(dialog_id, inScheduleMode, true); + getMessagesController().setLastVisibleDialogId(dialog_id, chatMode == MODE_SCHEDULED, true); if (scrollToTopOnResume) { if (scrollToTopUnReadOnResume && scrollToMessage != null) { if (chatListView != null) { @@ -15156,11 +16427,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MediaController.getInstance().stopRaiseToEarSensors(this, true); paused = true; wasPaused = true; - if (!inScheduleMode) { + if (chatMode == 0) { getNotificationsController().setOpenedDialogId(0); } Bulletin.removeDelegate(this); - getMessagesController().setLastVisibleDialogId(dialog_id, inScheduleMode, false); + getMessagesController().setLastVisibleDialogId(dialog_id, chatMode == MODE_SCHEDULED, false); CharSequence draftMessage = null; MessageObject replyMessage = null; boolean searchWebpage = true; @@ -15183,7 +16454,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (contentView != null) { contentView.onPause(); } - if (!inScheduleMode) { + if (chatMode == 0) { CharSequence[] message = new CharSequence[]{draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); getMediaDataController().saveDraft(dialog_id, threadMessageId, message[0], entities, replyMessage != null ? replyMessage.messageOwner : null, !searchWebpage); @@ -15260,13 +16531,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatLeaveTime = System.currentTimeMillis(); updateInformationForScreenshotDetector(); } - - if (undoView != null) { - undoView.hide(true, 0); - } - if (topUndoView != null) { - topUndoView.hide(true, 0); - } + hideUndoViews(); } if (chatListItemAniamtor != null) { @@ -15281,7 +16546,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void applyDraftMaybe(boolean canClear) { - if (chatActivityEnterView == null || inScheduleMode) { + if (chatActivityEnterView == null || chatMode != 0) { return; } TLRPC.DraftMessage draftMessage = getMediaDataController().getDraft(dialog_id, threadMessageId); @@ -15422,7 +16687,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (AndroidUtilities.isSmallTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { actionBar.setBackButtonDrawable(new BackDrawable(false)); if (fragmentContextView != null && fragmentContextView.getParent() == null) { - ((ViewGroup) fragmentView).addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + ((ViewGroup) fragmentView).addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); } } else { actionBar.setBackButtonDrawable(new BackDrawable(parentLayout == null || parentLayout.fragmentsStack.isEmpty() || parentLayout.fragmentsStack.get(0) == ChatActivity.this || parentLayout.fragmentsStack.size() == 1)); @@ -15569,7 +16834,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (finalSelectedObject == null && (selectedMessagesIds[0].size() + selectedMessagesIds[1].size()) == 0) { return; } - AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, inScheduleMode, loadParticipant, () -> { + AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, chatMode == MODE_SCHEDULED, loadParticipant, () -> { hideActionMode(); updatePinnedMessageView(true); }); @@ -15585,6 +16850,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cantDeleteMessagesCount = 0; canEditMessagesCount = 0; cantForwardMessagesCount = 0; + canSaveMusicCount = 0; + canSaveDocumentsCount = 0; + cantSaveMessagesCount = 0; if (chatActivityEnterView != null) { EditTextCaption editTextCaption = chatActivityEnterView.getEditField(); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { @@ -15645,7 +16913,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (single) { if (message.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { if (message.getReplyMsgId() != 0) { - scrollToMessageId(message.getReplyMsgId(), message.messageOwner.id, true, 0, true); + scrollToMessageId(message.getReplyMsgId(), message.messageOwner.id, true, 0, false); } else { Toast.makeText(getParentActivity(), LocaleController.getString("MessageNotFound", R.string.MessageNotFound), Toast.LENGTH_SHORT).show(); } @@ -15678,12 +16946,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean allowChatActions = true; boolean allowPin; - if (inScheduleMode || isThreadChat()) { + if (chatMode == MODE_SCHEDULED || isThreadChat()) { allowPin = false; } else if (currentChat != null) { allowPin = message.getDialogId() != mergeDialogId && ChatObject.canPinMessages(currentChat); } else if (currentEncryptedChat == null) { - if (userInfo != null) { + if (UserObject.isDeleted(currentUser)) { + allowPin = false; + } else if (userInfo != null) { allowPin = userInfo.can_pin_message; } else { allowPin = false; @@ -15692,7 +16962,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not allowPin = false; } allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); - boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (chatInfo != null && chatInfo.pinned_msg_id == message.getId() || userInfo != null && userInfo.pinned_msg_id == message.getId()); + boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId; if (allowEdit && groupedMessages != null) { int captionsCount = 0; @@ -15707,7 +16977,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } allowEdit = captionsCount < 2; } - if (inScheduleMode || threadMessageObjects != null && threadMessageObjects.contains(message) || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || + if (chatMode == MODE_SCHEDULED || threadMessageObjects != null && threadMessageObjects.contains(message) || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || type == 1 && message.getDialogId() == mergeDialogId || message.messageOwner.action instanceof TLRPC.TL_messageActionSecureValuesSent || currentEncryptedChat == null && message.getId() < 0 || @@ -15751,12 +17021,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(8); icons.add(R.drawable.msg_reply); } - if (currentChat.has_link && !isThreadChat() && !inScheduleMode && currentChat.has_link && currentChat.megagroup && message.canViewThread()) { - if (message.hasReplies()) { - items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); - } else { - items.add(LocaleController.getString("ViewThread", R.string.ViewThread)); - } + if (!isThreadChat() && chatMode != MODE_SCHEDULED && message.hasReplies() && currentChat.megagroup && message.canViewThread()) { + items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); options.add(27); icons.add(R.drawable.msg_viewreplies); } @@ -15786,7 +17052,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_reply); } } - if (message.canDeleteMessage(inScheduleMode, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { + if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); icons.add(R.drawable.msg_delete); @@ -15803,7 +17069,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_delete); } else { if (currentEncryptedChat == null) { - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { items.add(LocaleController.getString("MessageScheduleSend", R.string.MessageScheduleSend)); options.add(100); icons.add(R.drawable.outline_send); @@ -15829,7 +17095,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(3); icons.add(R.drawable.msg_copy); } - if (!isThreadChat() && !inScheduleMode && currentChat != null && currentChat.has_link && currentChat.megagroup && message.canViewThread()) { + if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { if (message.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); } else { @@ -15838,13 +17104,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(27); icons.add(R.drawable.msg_viewreplies); } - if (!inScheduleMode && ChatObject.isChannel(currentChat) && selectedObject.getDialogId() != mergeDialogId) { + if (chatMode != MODE_SCHEDULED && ChatObject.isChannel(currentChat) && selectedObject.getDialogId() != mergeDialogId) { items.add(LocaleController.getString("CopyLink", R.string.CopyLink)); options.add(22); icons.add(R.drawable.msg_link); } if (type == 2) { - if (!inScheduleMode) { + if (chatMode != MODE_SCHEDULED) { if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { if (message.canUnvote()) { items.add(LocaleController.getString("Unvote", R.string.Unvote)); @@ -15862,6 +17128,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(26); icons.add(R.drawable.msg_pollstop); } + } else if (selectedObject.isMusic()) { + items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); + options.add(10); + icons.add(R.drawable.msg_download); + } else if (selectedObject.isDocument()) { + items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + options.add(10); + icons.add(R.drawable.msg_download); } } } else if (type == 3) { @@ -15987,11 +17261,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_unfave); } } - if (!inScheduleMode && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { + if (chatMode != MODE_SCHEDULED && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(2); icons.add(R.drawable.msg_forward); } +// if (message.messageOwner.forwards > 0 && (BuildVars.DEBUG_PRIVATE_VERSION || ChatObject.hasAdminRights(getCurrentChat()))) { +// items.add(LocaleController.getString("ViewStats", R.string.ViewStats)); +// options.add(28); +// icons.add(R.drawable.msg_stats); +// } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(14); @@ -16006,12 +17285,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(12); icons.add(R.drawable.msg_edit); } - if (inScheduleMode && selectedObject.canEditMessageScheduleTime(currentChat)) { + if (chatMode == MODE_SCHEDULED && selectedObject.canEditMessageScheduleTime(currentChat)) { items.add(LocaleController.getString("MessageScheduleEditTime", R.string.MessageScheduleEditTime)); options.add(102); icons.add(R.drawable.msg_schedule); } - if (!inScheduleMode && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { + if (chatMode != MODE_SCHEDULED && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { if (UserObject.isReplyUser(currentUser)) { items.add(LocaleController.getString("BlockContact", R.string.BlockContact)); options.add(23); @@ -16022,7 +17301,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_report); } } - if (message.canDeleteMessage(inScheduleMode, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { + if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); icons.add(R.drawable.msg_delete); @@ -16038,7 +17317,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(3); icons.add(R.drawable.msg_copy); } - if (!isThreadChat() && !inScheduleMode && currentChat != null && currentChat.has_link && currentChat.megagroup && message.canViewThread()) { + if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { if (message.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); } else { @@ -16182,7 +17461,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not linearLayout.addView(cell); final int i = a; cell.setOnClickListener(v1 -> { - if (selectedObject == null || i < 0 || i >= options.size()) { + if (selectedObject == null || i >= options.size()) { return; } processSelectedOption(options.get(i)); @@ -16235,6 +17514,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }; + scrimPopupWindow.setPauseNotifications(true); scrimPopupWindow.setDismissAnimationDuration(220); scrimPopupWindow.setOutsideTouchable(true); scrimPopupWindow.setClippingEnabled(true); @@ -16420,12 +17700,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void restartSticker(ChatMessageCell cell) { MessageObject message = cell.getMessageObject(); TLRPC.Document document = message.getDocument(); - if (message.isAnimatedEmoji() || MessageObject.isAnimatedStickerDocument(document, currentEncryptedChat == null || message.isOut()) && !SharedConfig.loopStickers) { + boolean isEmoji; + if ((isEmoji = message.isAnimatedEmoji()) || MessageObject.isAnimatedStickerDocument(document, currentEncryptedChat == null || message.isOut()) && !SharedConfig.loopStickers) { ImageReceiver imageReceiver = cell.getPhotoImage(); RLottieDrawable drawable = imageReceiver.getLottieAnimation(); if (drawable != null) { - drawable.restart(); - if (message.isAnimatedEmoji()) { + if (isEmoji) { String emoji = message.getStickerEmoji(); if (EmojiData.isHeartEmoji(emoji)) { HashMap pattern = new HashMap<>(); @@ -16440,8 +17720,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not HashMap pattern = new HashMap<>(); pattern.put(34, 1); drawable.setVibrationPattern(pattern); + } else if (EmojiData.isCofinEmoji(emoji)) { + HashMap pattern = new HashMap<>(); + pattern.put(24, 0); + pattern.put(36, 0); + drawable.setVibrationPattern(pattern); + } + if (!drawable.isRunning() && emoji != null) { + MessagesController.EmojiSound sound = getMessagesController().emojiSounds.get(emoji.replace("\uFE0F", "")); + if (sound != null) { + getMediaController().playEmojiSound(getAccountInstance(), emoji, sound, false); + } } } + drawable.restart(); } } } @@ -16474,6 +17766,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return str; } + private void unpinMessage(MessageObject messageObject) { + if (messageObject == null) { + return; + } + ArrayList objects = new ArrayList<>(); + objects.add(selectedObject); + ArrayList ids = new ArrayList<>(); + ids.add(messageObject.getId()); + int oldTotalPinnedCount = totalPinnedMessagesCount; + getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, false, null, null, 0, totalPinnedMessagesCount - 1, pinnedEndReached); + pinBulletin = BulletinFactory.createUnpinMessageBulletin(this, + () -> { + getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, true, objects, null, 0, oldTotalPinnedCount, pinnedEndReached); + pinBulletin = null; + }, + () -> { + getMessagesController().pinMessage(currentChat, currentUser, messageObject.getId(), true, false, false); + pinBulletin = null; + }).show(); + } + private void saveMessageToGallery(MessageObject messageObject) { String path = messageObject.messageOwner.attachPath; if (!TextUtils.isEmpty(path)) { @@ -16501,13 +17814,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not success = false; } } - if (success && !inScheduleMode) { + if (success && chatMode == 0) { moveScrollToLastMessage(); } } else { if (getSendMessagesHelper().retrySendMessage(selectedObject, false)) { updateVisibleRows(); - if (!inScheduleMode) { + if (chatMode == 0) { moveScrollToLastMessage(); } } @@ -16559,11 +17872,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (selectedObjectGroup != null) { - for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { - saveMessageToGallery(selectedObjectGroup.messages.get(a)); + int filesAmount = selectedObjectGroup.messages.size(); + boolean allPhotos = true, allVideos = true; + for (int a = 0; a < filesAmount; a++) { + MessageObject messageObject = selectedObjectGroup.messages.get(a); + saveMessageToGallery(messageObject); + allPhotos &= messageObject.isPhoto(); + allVideos &= messageObject.isVideo(); } + final BulletinFactory.FileType fileType; + if (allPhotos) { + fileType = BulletinFactory.FileType.PHOTOS; + } else if (allVideos) { + fileType = BulletinFactory.FileType.VIDEOS; + } else { + fileType = BulletinFactory.FileType.MEDIA; + } + BulletinFactory.of(this).createDownloadBulletin(fileType, filesAmount).show(); } else { saveMessageToGallery(selectedObject); + BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo()).show(); } break; } @@ -16670,6 +17998,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } MediaController.saveFile(path, getParentActivity(), 0, null, null); + BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo()).show(); break; } case 8: { @@ -16690,21 +18019,53 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedObjectToEditCaption = null; return; } - String fileName = FileLoader.getDocumentFileName(selectedObject.getDocument()); - if (TextUtils.isEmpty(fileName)) { - fileName = selectedObject.getFileName(); - } - String path = selectedObject.messageOwner.attachPath; - if (path != null && path.length() > 0) { - File temp = new File(path); - if (!temp.exists()) { - path = null; + boolean isMusic = selectedObject.isMusic(); + boolean isDocument = selectedObject.isDocument(); + if (isMusic || isDocument) { + ArrayList messageObjects; + if (selectedObjectGroup != null) { + messageObjects = new ArrayList<>(selectedObjectGroup.messages); + } else { + messageObjects = new ArrayList<>(); + messageObjects.add(selectedObject); } + MediaController.saveFilesFromMessages(getParentActivity(), getAccountInstance(), messageObjects, (count) -> { + if (count > 0) { + BulletinFactory.of(this).createDownloadBulletin(isMusic ? BulletinFactory.FileType.AUDIOS : BulletinFactory.FileType.UNKNOWNS, count).show(); + } + }); + } else { + boolean video = selectedObject.isVideo(); + boolean photo = selectedObject.isPhoto(); + boolean gif = selectedObject.isGif(); + String fileName = FileLoader.getDocumentFileName(selectedObject.getDocument()); + if (TextUtils.isEmpty(fileName)) { + fileName = selectedObject.getFileName(); + } + String path = selectedObject.messageOwner.attachPath; + if (path != null && path.length() > 0) { + File temp = new File(path); + if (!temp.exists()) { + path = null; + } + } + if (path == null || path.length() == 0) { + path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + } + MediaController.saveFile(path, getParentActivity(), 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : "", () -> { + final BulletinFactory.FileType fileType; + if (photo) { + fileType = BulletinFactory.FileType.PHOTO_TO_DOWNLOADS; + } else if (video) { + fileType = BulletinFactory.FileType.VIDEO_TO_DOWNLOADS; + } else if (gif) { + fileType = BulletinFactory.FileType.GIF; + } else { + fileType = BulletinFactory.FileType.UNKNOWN; + } + BulletinFactory.of(this).createDownloadBulletin(fileType).show(); + }); } - if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); - } - MediaController.saveFile(path, getParentActivity(), selectedObject.isMusic() ? 3 : 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : ""); break; } case 11: { @@ -16726,45 +18087,88 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case 13: { - final int mid = selectedObject.getId(); + final int mid; + if (selectedObjectGroup != null && !selectedObjectGroup.messages.isEmpty()) { + mid = selectedObjectGroup.messages.get(0).getId(); + } else { + mid = selectedObject.getId(); + } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("PinMessageAlertTitle", R.string.PinMessageAlertTitle)); final boolean[] checks; if (currentUser != null) { - builder.setMessage(LocaleController.getString("PinMessageAlertChat", R.string.PinMessageAlertChat)); - checks = new boolean[]{false}; + if (currentPinnedMessageId != 0 && mid < currentPinnedMessageId) { + builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); + } else { + builder.setMessage(LocaleController.getString("PinMessageAlertChat", R.string.PinMessageAlertChat)); + } + checks = new boolean[]{false, false}; + if (!UserObject.isUserSelf(currentUser)) { + FrameLayout frameLayout = new FrameLayout(getParentActivity()); + CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell.setText(LocaleController.formatString("PinAlsoFor", R.string.PinAlsoFor, UserObject.getFirstName(currentUser)), "", false, false); + cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0); + frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0)); + cell.setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + checks[1] = !checks[1]; + cell1.setChecked(checks[1], true); + }); + builder.setView(frameLayout); + } } else if (ChatObject.isChannel(currentChat) && currentChat.megagroup || currentChat != null && !ChatObject.isChannel(currentChat)) { - builder.setMessage(LocaleController.getString("PinMessageAlert", R.string.PinMessageAlert)); - checks = new boolean[]{true}; - FrameLayout frameLayout = new FrameLayout(getParentActivity()); - CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell.setText(LocaleController.formatString("PinNotify", R.string.PinNotify), "", true, false); - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0)); - cell.setOnClickListener(v -> { - CheckBoxCell cell1 = (CheckBoxCell) v; - checks[0] = !checks[0]; - cell1.setChecked(checks[0], true); - }); - builder.setView(frameLayout); + if (!pinnedMessageIds.isEmpty() && mid < pinnedMessageIds.get(0)) { + builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); + checks = new boolean[]{false, true}; + } else { + builder.setMessage(LocaleController.getString("PinMessageAlert", R.string.PinMessageAlert)); + checks = new boolean[]{true, true}; + FrameLayout frameLayout = new FrameLayout(getParentActivity()); + CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell.setText(LocaleController.getString("PinNotify", R.string.PinNotify), "", true, false); + cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0); + frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0)); + cell.setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + checks[0] = !checks[0]; + cell1.setChecked(checks[0], true); + }); + builder.setView(frameLayout); + } } else { - builder.setMessage(LocaleController.getString("PinMessageAlertChannel", R.string.PinMessageAlertChannel)); - checks = new boolean[]{false}; + if (currentPinnedMessageId != 0 && mid < currentPinnedMessageId) { + builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); + } else { + builder.setMessage(LocaleController.getString("PinMessageAlertChannel", R.string.PinMessageAlertChannel)); + } + checks = new boolean[]{false, true}; } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> getMessagesController().pinMessage(currentChat, currentUser, mid, checks[0])); + builder.setPositiveButton(LocaleController.getString("PinMessage", R.string.PinMessage), (dialogInterface, i) -> { + getMessagesController().pinMessage(currentChat, currentUser, mid, false, !checks[1], checks[0]); + BulletinFactory.createPinMessageBulletin(this).show(); + }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); break; } case 14: { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("UnpinMessageAlertTitle", R.string.UnpinMessageAlertTitle)); - builder.setMessage(LocaleController.getString("UnpinMessageAlert", R.string.UnpinMessageAlert)); - builder.setPositiveButton(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), (dialogInterface, i) -> getMessagesController().pinMessage(currentChat, currentUser, 0, false)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); + MessageObject messageObject; + if (pinnedMessageObjects.containsKey(selectedObject.getId())) { + messageObject = selectedObject; + } else if (selectedObjectGroup != null && !selectedObjectGroup.messages.isEmpty()) { + messageObject = selectedObjectGroup.messages.get(0); + } else { + messageObject = selectedObject; + } + if (chatMode == MODE_PINNED && messages.size() == 2) { + finishFragment(); + chatActivityDelegate.onUnpin(false, false); + } else { + unpinMessage(messageObject); + } break; } case 15: { @@ -16933,6 +18337,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openDiscussionMessageChat(currentChat.id, null, selectedObject.getId(), 0, -1, 0, null); break; } + case 28: { + presentFragment(new MessageStatisticActivity(selectedObject)); + break; + } case 100: { if (!checkSlowMode(chatActivityEnterView.getSendButton())) { if (getMediaController().isPlayingMessage(selectedObject)) { @@ -17033,7 +18441,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.finishFragment(); } else { long did = dids.get(0); - if (did != dialog_id) { + if (did != dialog_id || chatMode == MODE_PINNED) { int lower_part = (int) did; int high_part = (int) (did >> 32); Bundle args = new Bundle(); @@ -17041,7 +18449,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (lower_part != 0) { if (lower_part > 0) { args.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { args.putInt("chat_id", -lower_part); } } else { @@ -17135,7 +18543,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public void onListItemAniamtorTick() { - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); if (scrimView != null) { fragmentView.invalidate(); } @@ -17327,7 +18735,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (text != null) { searchItem.setSearchFieldText(text, false); - getMediaDataController().searchMessagesInChat(text, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages); + getMediaDataController().searchMessagesInChat(text, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } updatePinnedMessageView(true); } @@ -17335,7 +18743,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didSelectLocation(TLRPC.MessageMedia location, int locationType, boolean notify, int scheduleDate) { getSendMessagesHelper().sendMessage(location, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate); - if (!inScheduleMode) { + if (chatMode == 0) { moveScrollToLastMessage(); } if (locationType == LocationActivity.LOCATION_TYPE_SEND || locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { @@ -17359,7 +18767,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public boolean isInScheduleMode() { - return inScheduleMode; + return chatMode == MODE_SCHEDULED; + } + + public int getChatMode() { + return chatMode; } public MessageObject getThreadMessage() { @@ -17428,10 +18840,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not afterMessageSend(); } else { if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, notify, scheduleDate); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate); afterMessageSend(); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, notify, scheduleDate); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate); afterMessageSend(); } } @@ -17525,7 +18937,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } TLRPC.messages_Messages historyFinal = history; int fnidFinal = fnid; - Utilities.stageQueue.postRunnable(() -> getMessagesController().processLoadedMessages(historyFinal, dialogId, 0, 30, maxReadId, 0, false, chatActivity.getClassGuid(), fnidFinal, 0, 0, 0, 2, true, false, false, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0)); + Utilities.stageQueue.postRunnable(() -> getMessagesController().processLoadedMessages(historyFinal, dialogId, 0, 30, maxReadId, 0, false, chatActivity.getClassGuid(), fnidFinal, 0, 0, 0, 2, true, false, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0)); } } @@ -17573,50 +18985,60 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; if (maxReadId >= 0 && linkedChatId != 0) { - int count = 30; TLRPC.Chat linkedChat = getMessagesController().getChat(linkedChatId); - TLRPC.TL_messages_getReplies getReplies = new TLRPC.TL_messages_getReplies(); - getReplies.peer = MessagesController.getInputPeer(linkedChat); - getReplies.msg_id = maxReadId; - getReplies.offset_date = 0; - getReplies.add_offset = -count + 10; - getReplies.limit = count; - getReplies.offset_id = maxReadId; - int guid = ++commentMessagesLoadingGuid; - commentMessagesRequestId = getConnectionsManager().sendRequest(getReplies, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (guid != commentMessagesLoadingGuid) { - return; - } - commentMessagesRequestId = -1; - if (response != null) { - savedHistory = (TLRPC.messages_Messages) response; - if (savedHistory.messages.size() > count) { - savedHistory.messages.remove(0); - } - } else { - savedNoHistory = true; - } - processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); - })); - getConnectionsManager().bindRequestToGuid(commentMessagesRequestId, classGuid); + if (linkedChat != null) { + int count = 30; + TLRPC.TL_messages_getReplies getReplies = new TLRPC.TL_messages_getReplies(); + getReplies.peer = MessagesController.getInputPeer(linkedChat); + getReplies.msg_id = maxReadId; + getReplies.offset_date = 0; + getReplies.add_offset = -count + 10; + getReplies.limit = count; + getReplies.offset_id = maxReadId; + int guid = ++commentMessagesLoadingGuid; + commentMessagesRequestId = getConnectionsManager().sendRequest(getReplies, (response, error) -> { + Runnable runnable = () -> { + if (guid != commentMessagesLoadingGuid) { + return; + } + commentMessagesRequestId = -1; + if (response != null) { + savedHistory = (TLRPC.messages_Messages) response; + if (savedHistory.messages.size() > count) { + savedHistory.messages.remove(0); + } + } else { + savedNoHistory = true; + } + processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); + }; + AndroidUtilities.runOnUIThread(() -> doOnIdle(runnable)); + }); + getConnectionsManager().bindRequestToGuid(commentMessagesRequestId, classGuid); + } else { + savedNoHistory = true; + } } else { savedNoHistory = true; } int guid = ++commentLoadingGuid; - commentRequestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (guid != commentLoadingGuid) { - return; - } - commentRequestId = -1; - if (response instanceof TLRPC.TL_messages_discussionMessage) { - savedDiscussionMessage = (TLRPC.TL_messages_discussionMessage) response; - getMessagesController().putUsers(savedDiscussionMessage.users, false); - getMessagesController().putChats(savedDiscussionMessage.chats, false); - } else { - savedNoDiscussion = true; - } - processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); - })); + commentRequestId = getConnectionsManager().sendRequest(req, (response, error) -> { + Runnable runnable = () -> { + if (guid != commentLoadingGuid) { + return; + } + commentRequestId = -1; + if (response instanceof TLRPC.TL_messages_discussionMessage) { + savedDiscussionMessage = (TLRPC.TL_messages_discussionMessage) response; + getMessagesController().putUsers(savedDiscussionMessage.users, false); + getMessagesController().putChats(savedDiscussionMessage.chats, false); + } else { + savedNoDiscussion = true; + } + processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); + }; + AndroidUtilities.runOnUIThread(() -> doOnIdle(runnable)); + }); getConnectionsManager().bindRequestToGuid(commentRequestId, classGuid); AndroidUtilities.runOnUIThread(progressRunnable, 500); } @@ -17668,7 +19090,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stringBuilder.setSpan(new URLSpan(""), index, index + request.domain.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } cells[a].setText(stringBuilder, "", true, false); - } else if (a == 1) { + } else { cells[a].setText(AndroidUtilities.replaceTags(LocaleController.formatString("OpenUrlOption2", R.string.OpenUrlOption2, UserObject.getFirstName(request.bot))), "", true, false); } cells[a].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); @@ -17797,7 +19219,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (str.startsWith("#") || str.startsWith("$")) { if (ChatObject.isChannel(currentChat)) { - if (inScheduleMode) { + if (chatMode == MODE_SCHEDULED) { chatActivityDelegate.openSearch(str); finishFragment(); } else { @@ -18028,7 +19450,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } MediaController.getInstance().cleanupPlayer(true, true, false, playingObject.equals(message)); } - if (inScheduleMode && (message.isVideo() || message.type == 1)) { + if (chatMode == MODE_SCHEDULED && (message.isVideo() || message.type == 1)) { PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); ArrayList arrayList = new ArrayList<>(); for (int a = 0, N = messages.size(); a < N; a++) { @@ -18108,7 +19530,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not rowCount += messages.size(); messagesEndRow = rowCount; - if (currentUser != null && currentUser.bot && !inScheduleMode && (botInfo.size() > 0 && botInfo.get(currentUser.id).description != null || UserObject.isReplyUser(currentUser)) && endReached[0]) { + if (currentUser != null && currentUser.bot && chatMode == 0 && (botInfo.size() > 0 && botInfo.get(currentUser.id).description != null || UserObject.isReplyUser(currentUser)) && endReached[0]) { botInfoRow = rowCount++; } else { botInfoRow = -5; @@ -18125,7 +19547,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messagesStartRow = -5; messagesEndRow = -5; - if (UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && !inScheduleMode) { + if (UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == 0) { botInfoRow = rowCount++; } else { botInfoRow = -5; @@ -18234,7 +19656,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.closeKeyboard(); } MessageObject messageObject = cell.getMessageObject(); - if ((UserObject.isReplyUser(currentUser) || UserObject.isUserSelf(currentUser)) && messageObject.messageOwner.fwd_from.saved_from_peer != null) { + if (chatMode == MODE_PINNED) { + chatActivityDelegate.openReplyMessage(messageObject.getId()); + finishFragment(); + } else if ((UserObject.isReplyUser(currentUser) || UserObject.isUserSelf(currentUser)) && messageObject.messageOwner.fwd_from.saved_from_peer != null) { if (UserObject.isReplyUser(currentUser) && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_to_top_id != 0) { openDiscussionMessageChat(messageObject.messageOwner.reply_to.reply_to_peer_id.channel_id, null, messageObject.messageOwner.reply_to.reply_to_top_id, 0, -1, messageObject.messageOwner.fwd_from.saved_from_msg_id, messageObject); } else { @@ -18309,7 +19734,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not VoIPHelper.startCall(currentUser, messageObject.isVideoCall(), userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id)); } } else { - createMenu(cell, true, false, otherX, otherY, false); + createMenu(cell, true, false, otherX, otherY, messageObject.isMusic()); } } @@ -18500,7 +19925,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not float lastDiff = 0; for (int a = 0, N = pollButtons.size(); a < N; a++) { ChatMessageCell.PollButton button = pollButtons.get(a); - lastDiff = cell.getY() + button.y - AndroidUtilities.dp(4) - chatListView.getPaddingTop(); + lastDiff = cell.getY() + button.y - AndroidUtilities.dp(4) - chatListViewPaddingTop; pollHintX = button.x + AndroidUtilities.dp(13.3f); pollHintY = button.y - AndroidUtilities.dp(6) + y; if (lastDiff > 0) { @@ -18561,7 +19986,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } MessageObject messageObject = cell.getMessageObject(); - if (inScheduleMode) { + if (chatMode == MODE_PINNED || chatMode == MODE_SCHEDULED) { chatActivityDelegate.openReplyMessage(id); finishFragment(); } else { @@ -18589,7 +20014,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void needReloadPolls() { - updateMessagesVisiblePart(false); + invalidateMessagesVisiblePart(); } @Override @@ -18644,16 +20069,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (message.isLiveLocation()) { - LocationActivity fragment = new LocationActivity(2); + LocationActivity fragment = new LocationActivity(currentChat == null || ChatObject.canSendMessages(currentChat) || currentChat.megagroup ? 2 : LocationActivity.LOCATION_TYPE_LIVE_VIEW); fragment.setDelegate(ChatActivity.this); fragment.setMessageObject(message); - fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } else { LocationActivity fragment = new LocationActivity(currentEncryptedChat == null ? 3 : 0); fragment.setDelegate(ChatActivity.this); fragment.setMessageObject(message); - fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } } else if (message.type == 9 || message.type == 0) { @@ -18890,38 +20313,44 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) view; + MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); messageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser); messageCell.isBot = currentUser != null && currentUser.bot; messageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; messageCell.isThreadChat = threadMessageId != 0; - messageCell.hasDiscussion = !inScheduleMode && ChatObject.isChannel(currentChat) && currentChat.has_link && !currentChat.megagroup; - messageCell.linkedChatId = !inScheduleMode && chatInfo != null ? chatInfo.linked_chat_id : 0; - messageCell.hasLinkedChat = !inScheduleMode && currentChat != null && currentChat.has_link; + messageCell.hasDiscussion = chatMode != MODE_SCHEDULED && ChatObject.isChannel(currentChat) && currentChat.has_link && !currentChat.megagroup; + messageCell.isPinned = chatMode == 0 && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())); + messageCell.linkedChatId = chatMode != MODE_SCHEDULED && chatInfo != null ? chatInfo.linked_chat_id : 0; messageCell.isRepliesChat = UserObject.isReplyUser(currentUser); + messageCell.isPinnedChat = chatMode == MODE_PINNED; boolean pinnedBottom = false; boolean pinnedBottomByGroup = false; boolean pinnedTop = false; boolean pinnedTopByGroup = false; - MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); int prevPosition; int nextPosition; if (groupedMessages != null) { MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); if (pos != null) { - if ((pos.flags & MessageObject.POSITION_FLAG_TOP) != 0) { + if (groupedMessages.isDocuments) { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; - } else { - pinnedTop = true; - pinnedTopByGroup = true; - prevPosition = -100; - } - if ((pos.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { nextPosition = position - groupedMessages.posArray.size() + groupedMessages.posArray.indexOf(pos); } else { - pinnedBottom = true; - pinnedBottomByGroup = true; - nextPosition = -100; + if ((pos.flags & MessageObject.POSITION_FLAG_TOP) != 0) { + prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; + } else { + pinnedTop = true; + pinnedTopByGroup = true; + prevPosition = -100; + } + if ((pos.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + nextPosition = position - groupedMessages.posArray.size() + groupedMessages.posArray.indexOf(pos); + } else { + pinnedBottom = true; + pinnedBottomByGroup = true; + nextPosition = -100; + } } } else { prevPosition = -100; @@ -18933,6 +20362,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int nextType = getItemViewType(nextPosition); int prevType = getItemViewType(prevPosition); + if (!message.hasReactions() && !(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { MessageObject nextMessage = messages.get(nextPosition - messagesStartRow); pinnedBottom = nextMessage.isOutOwner() == message.isOutOwner() && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; @@ -18940,7 +20370,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentChat != null) { int fromId = nextMessage.getFromChatId(); pinnedBottom = fromId == message.getFromChatId(); - if (pinnedBottom && fromId < 0 && currentChat.megagroup) { + if (!pinnedBottomByGroup && pinnedBottom && fromId < 0 && currentChat.megagroup) { pinnedBottom = false; } } else if (UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser)) { @@ -18959,7 +20389,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentChat != null) { int fromId = prevMessage.getFromChatId(); pinnedTop = fromId == message.getFromChatId(); - if (pinnedTop && fromId < 0 && currentChat.megagroup) { + if (!pinnedTopByGroup && pinnedTop && fromId < 0 && currentChat.megagroup) { pinnedTop = false; } } else if (UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser)) { @@ -19110,6 +20540,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (hintMessageObject != null && hintMessageObject.equals(message)) { messageCell.showHintButton(false, false, hintMessageType); } + if (message.isAnimatedEmoji()) { + String emoji = message.getStickerEmoji(); + if (emoji != null) { + MessagesController.EmojiSound sound = getMessagesController().emojiSounds.get(emoji.replace("\uFE0F", "")); + if (sound != null) { + getMediaController().playEmojiSound(getAccountInstance(), emoji, sound, true); + } + } + } boolean selected = false; boolean disableSelection = false; @@ -19172,7 +20611,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject message = messages.get(position - messagesStartRow); View view = holder.itemView; if (message != null && message.messageOwner != null && message.messageOwner.media_unread && message.messageOwner.mentioned) { - if (!inPreviewMode && !inScheduleMode) { + if (!inPreviewMode && chatMode == 0) { if (!message.isVoice() && !message.isRoundVideo()) { newMentionsCount--; if (newMentionsCount <= 0) { @@ -19224,6 +20663,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + public void invalidateRowWithMessageObject(MessageObject messageObject) { + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = chatListView.getChildAt(a); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + if (cell.getMessageObject() == messageObject) { + cell.invalidate(); + return; + } + } + } + } + public View updateRowWithMessageObject(MessageObject messageObject, boolean allowInPlace) { if (allowInPlace) { int count = chatListView.getChildCount(); @@ -19414,7 +20867,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openDiscussionMessageChat(currentChat.id, null, threadId, 0, -1, 0, null); } else { showScrollToMessageError = true; - scrollToMessageId(messageId, fromMessageId, true, 0, false); + if (chatMode == MODE_PINNED) { + chatActivityDelegate.openReplyMessage(messageId); + finishFragment(); + } else { + scrollToMessageId(messageId, fromMessageId, true, 0, false); + } } return true; } @@ -19433,7 +20891,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { int messageId = Integer.parseInt(matcher.group(3)); showScrollToMessageError = true; - scrollToMessageId(messageId, fromMessageId, true, 0, false); + if (chatMode == MODE_PINNED) { + chatActivityDelegate.openReplyMessage(messageId); + finishFragment(); + } else { + scrollToMessageId(messageId, fromMessageId, true, 0, false); + } } return true; } else if (urlFinal.startsWith("tg:resolve") || urlFinal.startsWith("tg://resolve")) { @@ -19447,7 +20910,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (threadId != 0 || commentId != 0) { return false; } else { - scrollToMessageId(messageId, fromMessageId, true, 0, false); + if (chatMode == MODE_PINNED) { + chatActivityDelegate.openReplyMessage(messageId); + finishFragment(); + } else { + scrollToMessageId(messageId, fromMessageId, true, 0, false); + } return true; } } @@ -19469,7 +20937,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } else { showScrollToMessageError = true; - scrollToMessageId(messageId, fromMessageId, true, 0, false); + if (chatMode == MODE_PINNED) { + chatActivityDelegate.openReplyMessage(messageId); + finishFragment(); + } else { + scrollToMessageId(messageId, fromMessageId, true, 0, false); + } return true; } } @@ -19573,6 +21046,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (instantCameraView != null) { instantCameraView.invalidateBlur(); } + + if (pinnedLineView != null) { + pinnedLineView.updateColors(); + } }; ArrayList themeDescriptions = new ArrayList<>(); @@ -19657,13 +21134,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInClockDrawable}, null, Theme.key_chat_inSentClock)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInSelectedClockDrawable}, null, Theme.key_chat_inSentClockSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgStickerHalfCheckDrawable, Theme.chat_msgStickerCheckDrawable, Theme.chat_msgStickerClockDrawable, Theme.chat_msgStickerViewsDrawable, Theme.chat_msgStickerRepliesDrawable}, null, Theme.key_chat_serviceText)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgStickerHalfCheckDrawable, Theme.chat_msgStickerCheckDrawable, Theme.chat_msgStickerClockDrawable, Theme.chat_msgStickerViewsDrawable, Theme.chat_msgStickerRepliesDrawable, Theme.chat_msgStickerPinnedDrawable}, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaClockDrawable}, null, Theme.key_chat_mediaSentClock)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsDrawable, Theme.chat_msgOutRepliesDrawable}, null, Theme.key_chat_outViews)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsSelectedDrawable, Theme.chat_msgOutRepliesSelectedDrawable}, null, Theme.key_chat_outViewsSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsDrawable, Theme.chat_msgInRepliesDrawable}, null, Theme.key_chat_inViews)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsSelectedDrawable, Theme.chat_msgInRepliesSelectedDrawable}, null, Theme.key_chat_inViewsSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaViewsDrawable, Theme.chat_msgMediaRepliesDrawable}, null, Theme.key_chat_mediaViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsDrawable, Theme.chat_msgOutRepliesDrawable, Theme.chat_msgOutPinnedDrawable}, null, Theme.key_chat_outViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutViewsSelectedDrawable, Theme.chat_msgOutRepliesSelectedDrawable, Theme.chat_msgOutPinnedSelectedDrawable}, null, Theme.key_chat_outViewsSelected)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsDrawable, Theme.chat_msgInRepliesDrawable, Theme.chat_msgInPinnedDrawable}, null, Theme.key_chat_inViews)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsSelectedDrawable, Theme.chat_msgInRepliesSelectedDrawable, Theme.chat_msgInPinnedSelectedDrawable}, null, Theme.key_chat_inViewsSelected)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaViewsDrawable, Theme.chat_msgMediaRepliesDrawable, Theme.chat_msgMediaPinnedDrawable}, null, Theme.key_chat_mediaViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutMenuDrawable}, null, Theme.key_chat_outMenu)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutMenuSelectedDrawable}, null, Theme.key_chat_outMenuSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInMenuDrawable}, null, Theme.key_chat_inMenu)); @@ -19946,12 +21423,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); - themeDescriptions.add(new ThemeDescription(pinnedLineView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_chat_topPanelLine)); - themeDescriptions.add(new ThemeDescription(pinnedMessageNameTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); - themeDescriptions.add(new ThemeDescription(pinnedMessageTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelMessage)); + themeDescriptions.add(new ThemeDescription(pinnedLineView, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_topPanelLine)); + themeDescriptions.add(new ThemeDescription(pinnedLineView, 0, null, null, null, selectedBackgroundDelegate, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(pinnedCounterTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); + for (int a = 0; a < 2; a++) { + themeDescriptions.add(new ThemeDescription(pinnedNameTextView[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); + themeDescriptions.add(new ThemeDescription(pinnedMessageTextView[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelMessage)); + } themeDescriptions.add(new ThemeDescription(alertNameTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); themeDescriptions.add(new ThemeDescription(alertTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelMessage)); themeDescriptions.add(new ThemeDescription(closePinned, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); + themeDescriptions.add(new ThemeDescription(pinnedListButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); themeDescriptions.add(new ThemeDescription(closeReportSpam, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); themeDescriptions.add(new ThemeDescription(topChatPanelView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); themeDescriptions.add(new ThemeDescription(alertView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index 60760df28..5932bf31d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -44,7 +44,6 @@ 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.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -196,7 +195,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image return false; } if (info == null) { - info = MessagesStorage.getInstance(currentAccount).loadChatInfo(chatId, new CountDownLatch(1), false, false); + info = MessagesStorage.getInstance(currentAccount).loadChatInfo(chatId, ChatObject.isChannel(currentChat), new CountDownLatch(1), false, false); if (info == null) { return false; } @@ -1143,7 +1142,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (nameTextView != null) { String text = nameTextView.getText().toString(); - if (text != null && text.length() != 0) { + if (text.length() != 0) { args.putString("nameTextView", text); } } @@ -1265,7 +1264,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (stickersCell != null) { - if (info.stickerset != null) { + if (info != null && info.stickerset != null) { stickersCell.setTextAndValue(LocaleController.getString("GroupStickers", R.string.GroupStickers), info.stickerset.title, false); } else { stickersCell.setText(LocaleController.getString("GroupStickers", R.string.GroupStickers), false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java index a61d9cfc0..7d99d04ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java @@ -123,7 +123,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe return false; } if (info == null) { - info = getMessagesStorage().loadChatInfo(chatId, new CountDownLatch(1), false, false); + info = getMessagesStorage().loadChatInfo(chatId, ChatObject.isChannel(currentChat), new CountDownLatch(1), false, false); if (info == null) { return false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java index 78528d2d0..2a0f4a994 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java @@ -407,7 +407,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter } progressDialog[0] = null; info.linked_chat_id = 0; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false, null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false); AndroidUtilities.runOnUIThread(() -> getMessagesController().loadFullChat(currentChatId, 0, true), 1000); if (!isChannel) { finishFragment(); @@ -537,7 +537,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter progressDialog[0] = null; } info.linked_chat_id = chat.id; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false, null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, false); AndroidUtilities.runOnUIThread(() -> getMessagesController().loadFullChat(currentChatId, 0, true), 1000); if (createFragment != null) { removeSelfFromStack(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 8a134379a..ab21ff369 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -61,6 +61,7 @@ import org.telegram.ui.Cells.TextCheckCell2; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.ManageChatUserCell; import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.IntSeekBarAccessibilityDelegate; import org.telegram.ui.Components.LayoutHelper; @@ -1114,7 +1115,19 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } private void openRightsEdit2(int userId, int date, TLObject participant, TLRPC.TL_chatAdminRights adminRights, TLRPC.TL_chatBannedRights bannedRights, String rank, boolean canEditAdmin, int type, boolean removeFragment) { - ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, adminRights, defaultBannedRights, bannedRights, rank, type, true, false); + boolean[] needShowBulletin = new boolean[1]; + final boolean isAdmin = participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin; + ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, adminRights, defaultBannedRights, bannedRights, rank, type, true, false) { + @Override + protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (!isOpen && backward && needShowBulletin[0] && BulletinFactory.canShowBulletin(ChatUsersActivity.this)) { + final TLRPC.User user = getMessagesController().getUser(userId); + if (user != null) { + BulletinFactory.createPromoteToAdminBulletin(ChatUsersActivity.this, user.first_name).show(); + } + } + } + }; fragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -1158,6 +1171,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente loadChatParticipants(0, 200); } } + if (rights == 1 && !isAdmin) { + needShowBulletin[0] = true; + } } else if (type == 1) { if (rights == 0) { removeParticipants(userId); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 0db4dd6cc..a59e7eac5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -8,16 +8,20 @@ package org.telegram.ui.Components; +import android.Manifest; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.graphics.Outline; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Vibrator; import android.text.Html; @@ -33,6 +37,7 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; +import android.view.ViewOutlineProvider; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.FrameLayout; @@ -95,6 +100,8 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; +import androidx.annotation.RequiresApi; + public class AlertsCreator { public static Dialog processError(int currentAccount, TLRPC.TL_error error, BaseFragment fragment, TLObject request, Object... args) { @@ -157,7 +164,7 @@ public class AlertsCreator { if (fragment != null) { showSimpleAlert(fragment, LocaleController.getString("EditMessageError", R.string.EditMessageError)); } else { - showSimpleToast(fragment, LocaleController.getString("EditMessageError", R.string.EditMessageError)); + showSimpleToast(null, LocaleController.getString("EditMessageError", R.string.EditMessageError)); } } } else if (request instanceof TLRPC.TL_messages_sendMessage || @@ -216,7 +223,7 @@ public class AlertsCreator { } else if (request instanceof TLRPC.TL_account_sendConfirmPhoneCode) { if (error.code == 400) { return showSimpleAlert(fragment, LocaleController.getString("CancelLinkExpired", R.string.CancelLinkExpired)); - } else if (error.text != null) { + } else { if (error.text.startsWith("FLOOD_WAIT")) { return showSimpleAlert(fragment, LocaleController.getString("FloodWait", R.string.FloodWait)); } else { @@ -262,7 +269,7 @@ public class AlertsCreator { break; } } else if (request instanceof TLRPC.TL_contacts_importContacts) { - if (error == null || error.text.startsWith("FLOOD_WAIT")) { + if (error.text.startsWith("FLOOD_WAIT")) { showSimpleAlert(fragment, LocaleController.getString("FloodWait", R.string.FloodWait)); } else { showSimpleAlert(fragment, LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); @@ -395,7 +402,7 @@ public class AlertsCreator { int end; if (start != -1) { end = TextUtils.indexOf(spanned, ']', start + 1); - if (start != -1 && end != -1) { + if (end != -1) { spanned.delete(end, end + 1); spanned.delete(start, start + 1); } @@ -434,7 +441,7 @@ public class AlertsCreator { if (!few) { TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(chat.id); if (chatFull == null) { - chatFull = MessagesStorage.getInstance(currentAccount).loadChatInfo(chat.id, new CountDownLatch(1), false, false); + chatFull = MessagesStorage.getInstance(currentAccount).loadChatInfo(chat.id, ChatObject.isChannel(chat), new CountDownLatch(1), false, false); } if (chatFull != null && chatFull.slowmode_next_send_date >= ConnectionsManager.getInstance(currentAccount).getCurrentTime()) { few = true; @@ -575,7 +582,7 @@ public class AlertsCreator { cells[a].setTag(a); if (a == 0) { cells[a].setText(LocaleController.getString("DeleteReportSpam", R.string.DeleteReportSpam), "", true, false); - } else if (a == 1) { + } else { cells[a].setText(LocaleController.formatString("DeleteThisChat", R.string.DeleteThisChat), "", true, false); } cells[a].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); @@ -1158,7 +1165,7 @@ public class AlertsCreator { avatarDrawable.setInfo(user); imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } - } else if (chat != null) { + } else { avatarDrawable.setInfo(chat); imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } @@ -1181,7 +1188,7 @@ public class AlertsCreator { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user)))); } } - } else if (chat != null) { + } else { if (!ChatObject.isChannel(chat) || chat.megagroup && TextUtils.isEmpty(chat.username)) { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithChat", R.string.AreYouSureClearHistoryWithChat, chat.title))); } else if (chat.megagroup) { @@ -2506,7 +2513,48 @@ public class AlertsCreator { return builder.create(); } - public static AlertDialog.Builder createContactsPermissionDialog(final Activity parentActivity, final MessagesStorage.IntCallback callback) { + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static AlertDialog.Builder createBackgroundLocationPermissionDialog(Activity activity, TLRPC.User selfUser, Runnable cancelRunnable) { + if (activity == null || Build.VERSION.SDK_INT < 29) { + return null; + } + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + String svg = RLottieDrawable.readRes(null, Theme.getCurrentTheme().isDark() ? R.raw.permission_map_dark : R.raw.permission_map); + String pinSvg = RLottieDrawable.readRes(null, Theme.getCurrentTheme().isDark() ? R.raw.permission_pin_dark : R.raw.permission_pin); + FrameLayout frameLayout = new FrameLayout(activity); + frameLayout.setClipToOutline(true); + frameLayout.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setRoundRect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight() + AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + } + }); + + View background = new View(activity); + background.setBackground(SvgHelper.getDrawable(svg)); + frameLayout.addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); + + View pin = new View(activity); + pin.setBackground(SvgHelper.getDrawable(pinSvg)); + frameLayout.addView(pin, LayoutHelper.createFrame(60, 82, Gravity.CENTER, 0, 0, 0, 0)); + + BackupImageView imageView = new BackupImageView(activity); + imageView.setRoundRadius(AndroidUtilities.dp(26)); + imageView.setImage(ImageLocation.getForUser(selfUser, false), "50_50", (Drawable) null, selfUser); + frameLayout.addView(imageView, LayoutHelper.createFrame(52, 52, Gravity.CENTER, 0, 0, 0, 11)); + + builder.setTopView(frameLayout); + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("PermissionBackgroundLocation", R.string.PermissionBackgroundLocation))); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { + if (activity.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 30); + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), ((dialog, which) -> cancelRunnable.run())); + return builder; + } + + public static AlertDialog.Builder createContactsPermissionDialog(Activity parentActivity, MessagesStorage.IntCallback callback) { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); builder.setTopImage(R.drawable.permissions_contacts, Theme.getColor(Theme.key_dialogTopBackground)); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("ContactsPermissionAlert", R.string.ContactsPermissionAlert))); @@ -2607,14 +2655,12 @@ public class AlertsCreator { LocaleController.getString("NotificationsPriorityUrgent", R.string.NotificationsPriorityUrgent) }; } else { - if (dialog_id == 0) { - if (globalType == NotificationsController.TYPE_PRIVATE) { - selected[0] = preferences.getInt("priority_messages", 1); - } else if (globalType == NotificationsController.TYPE_GROUP) { - selected[0] = preferences.getInt("priority_group", 1); - } else if (globalType == NotificationsController.TYPE_CHANNEL) { - selected[0] = preferences.getInt("priority_channel", 1); - } + if (globalType == NotificationsController.TYPE_PRIVATE) { + selected[0] = preferences.getInt("priority_messages", 1); + } else if (globalType == NotificationsController.TYPE_GROUP) { + selected[0] = preferences.getInt("priority_group", 1); + } else if (globalType == NotificationsController.TYPE_CHANNEL) { + selected[0] = preferences.getInt("priority_channel", 1); } if (selected[0] == 4) { selected[0] = 0; @@ -3072,7 +3118,7 @@ public class AlertsCreator { cell.setText(LocaleController.getString("DeleteBanUser", R.string.DeleteBanUser), "", false, false); } else if (a == 1) { cell.setText(LocaleController.getString("DeleteReportSpam", R.string.DeleteReportSpam), "", false, false); - } else if (a == 2) { + } else { cell.setText(LocaleController.formatString("DeleteAllFrom", R.string.DeleteAllFrom, ContactsController.formatName(actionUser.first_name, actionUser.last_name)), "", false, false); } cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); @@ -3114,7 +3160,12 @@ public class AlertsCreator { } else if (!scheduled && !ChatObject.isChannel(chat) && encryptedChat == null) { if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && (!user.bot || user.support) || chat != null) { if (selectedMessage != null) { - boolean hasOutgoing = !selectedMessage.isSendError() && (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) && (selectedMessage.isOut() || canRevokeInbox || ChatObject.hasAdminRights(chat)) && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; + boolean hasOutgoing = !selectedMessage.isSendError() && ( + selectedMessage.messageOwner.action == null || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) && (selectedMessage.isOut() || canRevokeInbox || ChatObject.hasAdminRights(chat)) && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; if (hasOutgoing) { myMessagesCount++; } @@ -3123,7 +3174,11 @@ public class AlertsCreator { for (int a = 1; a >= 0; a--) { for (int b = 0; b < selectedMessages[a].size(); b++) { MessageObject msg = selectedMessages[a].valueAt(b); - if (!(msg.messageOwner.action == null || msg.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall)) { + if (!(msg.messageOwner.action == null || + msg.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || + msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall || + msg.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage || + msg.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached)) { continue; } if ((msg.isOut() || canRevokeInbox) || chat != null && ChatObject.canBlockUsers(chat)) { @@ -3196,7 +3251,7 @@ public class AlertsCreator { int channelId = 0; if (!ids.isEmpty()) { MessageObject msg = selectedMessages[a].get(ids.get(0)); - if (channelId == 0 && msg.messageOwner.peer_id.channel_id != 0) { + if (msg.messageOwner.peer_id.channel_id != 0) { channelId = msg.messageOwner.peer_id.channel_id; } } @@ -3230,9 +3285,6 @@ public class AlertsCreator { MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat, userFinal, 0); } } - if (BulletinFactory.canShowBulletin(fragment)) { - BulletinFactory.createDeleteMessagesBulletin(fragment, count).show(); - } if (onDelete != null) { onDelete.run(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedNumberLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedNumberLayout.java new file mode 100644 index 000000000..d8f621ddd --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedNumberLayout.java @@ -0,0 +1,161 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.graphics.Canvas; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.Property; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; + +import java.util.ArrayList; +import java.util.Locale; + +public class AnimatedNumberLayout { + + private ArrayList letters = new ArrayList<>(); + private ArrayList oldLetters = new ArrayList<>(); + private final TextPaint textPaint; + private ObjectAnimator animator; + private float progress = 0.0f; + private int currentNumber = 1; + private final View parentView; + + public static final Property PROGRESS = new AnimationProperties.FloatProperty("progress") { + @Override + public void setValue(AnimatedNumberLayout object, float value) { + object.setProgress(value); + } + + @Override + public Float get(AnimatedNumberLayout object) { + return object.progress; + } + }; + + public AnimatedNumberLayout(View parent, TextPaint paint) { + textPaint = paint; + parentView = parent; + } + + private void setProgress(float value) { + if (progress == value) { + return; + } + progress = value; + parentView.invalidate(); + } + + private float getProgress() { + return progress; + } + + public int getWidth() { + float width = 0; + int count = letters.size(); + for (int a = 0; a < count; a++) { + width += letters.get(a).getLineWidth(0); + } + return (int) Math.ceil(width); + } + + public void setNumber(int number, boolean animated) { + if (currentNumber == number && !letters.isEmpty()) { + return; + } + if (animator != null) { + animator.cancel(); + animator = null; + } + oldLetters.clear(); + oldLetters.addAll(letters); + letters.clear(); + String oldText = String.format(Locale.US, "%d", currentNumber); + String text = String.format(Locale.US, "%d", number); + boolean forwardAnimation = number > currentNumber; + currentNumber = number; + progress = 0; + for (int a = 0; a < text.length(); a++) { + String ch = text.substring(a, a + 1); + String oldCh = !oldLetters.isEmpty() && a < oldText.length() ? oldText.substring(a, a + 1) : null; + if (oldCh != null && oldCh.equals(ch)) { + letters.add(oldLetters.get(a)); + oldLetters.set(a, null); + } else { + StaticLayout layout = new StaticLayout(ch, textPaint, (int) Math.ceil(textPaint.measureText(ch)), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + letters.add(layout); + } + } + if (animated && !oldLetters.isEmpty()) { + animator = ObjectAnimator.ofFloat(this, PROGRESS, forwardAnimation ? -1 : 1, 0); + animator.setDuration(150); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animator = null; + oldLetters.clear(); + } + }); + animator.start(); + } + parentView.invalidate(); + } + + public void draw(Canvas canvas) { + if (letters.isEmpty()) { + return; + } + float height = letters.get(0).getHeight(); + int count = Math.max(letters.size(), oldLetters.size()); + canvas.save(); + int currentAlpha = textPaint.getAlpha(); + for (int a = 0; a < count; a++) { + canvas.save(); + StaticLayout old = a < oldLetters.size() ? oldLetters.get(a) : null; + StaticLayout layout = a < letters.size() ? letters.get(a) : null; + if (progress > 0) { + if (old != null) { + textPaint.setAlpha((int) (currentAlpha * progress)); + canvas.save(); + canvas.translate(0, (progress - 1.0f) * height); + old.draw(canvas); + canvas.restore(); + if (layout != null) { + textPaint.setAlpha((int) (currentAlpha * (1.0f - progress))); + canvas.translate(0, progress * height); + } + } else { + textPaint.setAlpha(currentAlpha); + } + } else if (progress < 0) { + if (old != null) { + textPaint.setAlpha((int) (currentAlpha * -progress)); + canvas.save(); + canvas.translate(0, (1.0f + progress) * height); + old.draw(canvas); + canvas.restore(); + } + if (layout != null) { + if (a == count - 1 || old != null) { + textPaint.setAlpha((int) (currentAlpha * (1.0f + progress))); + canvas.translate(0, progress * height); + } else { + textPaint.setAlpha(currentAlpha); + } + } + } else if (layout != null) { + textPaint.setAlpha(currentAlpha); + } + if (layout != null) { + layout.draw(canvas); + } + canvas.restore(); + canvas.translate((layout != null ? layout.getLineWidth(0) : old.getLineWidth(0)), 0); + } + canvas.restore(); + } +} 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 f65b603c4..5907c3b41 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -13,20 +13,28 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; +import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; + +import androidx.annotation.NonNull; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -53,6 +61,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; @@ -82,6 +91,7 @@ import org.telegram.ui.LaunchActivity; import java.io.File; import java.util.ArrayList; +import java.util.List; public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate, DownloadController.FileDownloadProgressListener { @@ -100,11 +110,11 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. private TextView emptySubtitleTextView; private FrameLayout playerLayout; - private BackupImageView placeholderImageView; - private TextView titleTextView; - private ImageView prevButton; - private ImageView nextButton; - private TextView authorTextView; + private CoverContainer coverContainer; + private ClippingTextViewSwitcher titleTextView; + private RLottieImageView prevButton; + private RLottieImageView nextButton; + private ClippingTextViewSwitcher authorTextView; private ActionBarMenuItem optionsButton; private LineProgressView progressView; private SeekBarView seekBarView; @@ -117,6 +127,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. private ActionBarMenuSubItem shuffleListItem; private ActionBarMenuSubItem reverseOrderItem; private ImageView playButton; + private PlayPauseDrawable playPauseDrawable; private FrameLayout blurredView; private BackupImageView bigAlbumConver; private ActionBarMenuItem searchItem; @@ -134,6 +145,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. private int searchOpenOffset; private ArrayList playlist; + private MessageObject lastMessageObject; private int scrollOffsetY = Integer.MAX_VALUE; private int topBeforeSwitch; @@ -328,6 +340,23 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. canvas.drawRect(backgroundPaddingLeft, 0, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint); } } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Bulletin.addDelegate(this, new Bulletin.Delegate() { + @Override + public int getBottomOffset() { + return playerLayout.getHeight(); + } + }); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + Bulletin.removeDelegate(this); + } }; containerView.setWillNotDraw(false); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); @@ -444,7 +473,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } }; - placeholderImageView = new BackupImageView(context) { + coverContainer = new CoverContainer(context) { private long pressTime; @@ -452,7 +481,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { - if (imageReceiver.hasBitmapImage()) { + if (getImageReceiver().hasBitmapImage()) { showAlbumCover(true, true); pressTime = SystemClock.elapsedRealtime(); } @@ -463,28 +492,41 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } return true; } - }; - placeholderImageView.getImageReceiver().setDelegate((imageReceiver, set, thumb, memCache) -> { - if (blurredView.getTag() != null) { - bigAlbumConver.setImageBitmap(placeholderImageView.imageReceiver.getBitmap()); - } - }); - placeholderImageView.setRoundRadius(AndroidUtilities.dp(4)); - playerLayout.addView(placeholderImageView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.RIGHT, 0, 20, 20, 0)); - titleTextView = new TextView(context); - titleTextView.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle)); - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleTextView.setEllipsize(TextUtils.TruncateAt.END); - titleTextView.setSingleLine(true); + @Override + protected void onImageUpdated(ImageReceiver imageReceiver) { + if (blurredView.getTag() != null) { + bigAlbumConver.setImageBitmap(imageReceiver.getBitmap()); + } + } + }; + playerLayout.addView(coverContainer, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.RIGHT, 0, 20, 20, 0)); + + titleTextView = new ClippingTextViewSwitcher(context) { + @Override + protected TextView createTextView() { + final TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setSingleLine(true); + return textView; + } + }; playerLayout.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 20, 72, 0)); - authorTextView = new TextView(context); - authorTextView.setTextColor(Theme.getColor(Theme.key_player_time)); - authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); - authorTextView.setEllipsize(TextUtils.TruncateAt.END); - authorTextView.setSingleLine(true); + authorTextView = new ClippingTextViewSwitcher(context) { + @Override + protected TextView createTextView() { + final TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_player_time)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setSingleLine(true); + return textView; + } + }; playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 47, 72, 0)); seekBarView = new SeekBarView(context); @@ -616,20 +658,29 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. updateRepeatButton(); }); - buttons[1] = prevButton = new ImageView(context); + final int iconColor = Theme.getColor(Theme.key_player_button); + + buttons[1] = prevButton = new RLottieImageView(context); prevButton.setScaleType(ImageView.ScaleType.CENTER); - prevButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); - prevButton.setImageResource(R.drawable.player_new_previous); + prevButton.setAnimation(R.raw.player_prev, 20, 20); + prevButton.setLayerColor("Triangle 3.**", iconColor); + prevButton.setLayerColor("Triangle 4.**", iconColor); + prevButton.setLayerColor("Rectangle 4.**", iconColor); if (Build.VERSION.SDK_INT >= 21) { prevButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(22))); } bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); - prevButton.setOnClickListener(v -> MediaController.getInstance().playPreviousMessage()); + prevButton.setOnClickListener(v -> { + MediaController.getInstance().playPreviousMessage(); + prevButton.setProgress(0f); + prevButton.playAnimation(); + }); prevButton.setContentDescription(LocaleController.getString("AccDescrPrevious", R.string.AccDescrPrevious)); buttons[2] = playButton = new ImageView(context); playButton.setScaleType(ImageView.ScaleType.CENTER); - playButton.setImageResource(R.drawable.player_new_play); + playButton.setImageDrawable(playPauseDrawable = new PlayPauseDrawable(28)); + playPauseDrawable.setPause(!MediaController.getInstance().isMessagePaused(), false); playButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); if (Build.VERSION.SDK_INT >= 21) { playButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(24))); @@ -646,18 +697,25 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } }); - buttons[3] = nextButton = new ImageView(context); + buttons[3] = nextButton = new RLottieImageView(context); nextButton.setScaleType(ImageView.ScaleType.CENTER); - nextButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); - nextButton.setImageResource(R.drawable.player_new_next); + nextButton.setAnimation(R.raw.player_prev, 20, 20); + nextButton.setLayerColor("Triangle 3.**", iconColor); + nextButton.setLayerColor("Triangle 4.**", iconColor); + nextButton.setLayerColor("Rectangle 4.**", iconColor); + nextButton.setRotation(180f); if (Build.VERSION.SDK_INT >= 21) { nextButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(22))); } bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); - nextButton.setOnClickListener(v -> MediaController.getInstance().playNextMessage()); + nextButton.setOnClickListener(v -> { + MediaController.getInstance().playNextMessage(); + nextButton.setProgress(0f); + nextButton.playAnimation(); + }); nextButton.setContentDescription(LocaleController.getString("Next", R.string.Next)); - buttons[4] = optionsButton = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_player_button)); + buttons[4] = optionsButton = new ActionBarMenuItem(context, null, 0, iconColor); optionsButton.setLongClickEnabled(false); optionsButton.setShowSubmenuByMove(false); optionsButton.setIcon(R.drawable.ic_ab_other); @@ -821,6 +879,8 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. bigAlbumConver = new BackupImageView(context); bigAlbumConver.setAspectFit(true); bigAlbumConver.setRoundRadius(AndroidUtilities.dp(8)); + bigAlbumConver.setScaleX(0.9f); + bigAlbumConver.setScaleY(0.9f); blurredView.addView(bigAlbumConver, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 30, 30, 30, 30)); updateTitle(false); @@ -1065,7 +1125,9 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. if (path == null || path.length() == 0) { path = FileLoader.getPathToMessage(messageObject.messageOwner).toString(); } - MediaController.saveFile(path, parentActivity, 3, fileName, messageObject.getDocument() != null ? messageObject.getDocument().mime_type : ""); + MediaController.saveFile(path, parentActivity, 3, fileName, messageObject.getDocument() != null ? messageObject.getDocument().mime_type : "", () -> { + BulletinFactory.of((FrameLayout) containerView).createDownloadBulletin(BulletinFactory.FileType.AUDIO).show(); + }); } } @@ -1075,7 +1137,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. return; } blurredView.setTag(1); - bigAlbumConver.setImageBitmap(placeholderImageView.imageReceiver.getBitmap()); + bigAlbumConver.setImageBitmap(coverContainer.getImageReceiver().getBitmap()); blurredAnimationInProgress = true; BaseFragment fragment = parentActivity.getActionBarLayout().fragmentsStack.get(parentActivity.getActionBarLayout().fragmentsStack.size() - 1); View fragmentView = fragment.getFragmentView(); @@ -1096,6 +1158,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. blurredAnimationInProgress = false; } }).start(); + bigAlbumConver.animate().scaleX(1f).scaleY(1f).setDuration(180).start(); } else { if (blurredView.getVisibility() != View.VISIBLE) { return; @@ -1111,10 +1174,13 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. blurredAnimationInProgress = false; } }).start(); + bigAlbumConver.animate().scaleX(0.9f).scaleY(0.9f).setDuration(180).start(); } else { blurredView.setAlpha(0.0f); blurredView.setVisibility(View.INVISIBLE); bigAlbumConver.setImageBitmap(null); + bigAlbumConver.setScaleX(0.9f); + bigAlbumConver.setScaleY(0.9f); } } } @@ -1358,12 +1424,16 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } private void updateProgress(MessageObject messageObject) { + updateProgress(messageObject, false); + } + + private void updateProgress(MessageObject messageObject, boolean animated) { if (seekBarView != null) { int newTime; if (seekBarView.isDragging()) { newTime = (int) (messageObject.getDuration() * seekBarView.getProgress()); } else { - seekBarView.setProgress(messageObject.audioProgress); + seekBarView.setProgress(messageObject.audioProgress, animated); float bufferedProgress; if (currentAudioFinishedLoading) { @@ -1423,21 +1493,25 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. dismiss(); } else { if (messageObject == null) { + lastMessageObject = null; return; } + final boolean sameMessageObject = messageObject == lastMessageObject; + lastMessageObject = messageObject; if (messageObject.eventId != 0 || messageObject.getId() <= -2000000000) { optionsButton.setVisibility(View.INVISIBLE); } else { optionsButton.setVisibility(View.VISIBLE); } checkIfMusicDownloaded(messageObject); - updateProgress(messageObject); + updateProgress(messageObject, !sameMessageObject); + updateCover(messageObject, !sameMessageObject); if (MediaController.getInstance().isMessagePaused()) { - playButton.setImageResource(R.drawable.player_new_play); + playPauseDrawable.setPause(false); playButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } else { - playButton.setImageResource(R.drawable.player_new_pause); + playPauseDrawable.setPause(true); playButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } String title = messageObject.getMusicTitle(); @@ -1445,35 +1519,6 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. titleTextView.setText(title); authorTextView.setText(author); - String loadTitle = author + " " + title; - AudioInfo audioInfo = MediaController.getInstance().getAudioInfo(); - if (audioInfo != null && audioInfo.getCover() != null) { - placeholderImageView.setImageBitmap(audioInfo.getCover()); - currentFile = null; - currentAudioFinishedLoading = true; - } else { - TLRPC.Document document = messageObject.getDocument(); - currentFile = FileLoader.getAttachFileName(document); - currentAudioFinishedLoading = false; - TLRPC.PhotoSize thumb = document != null ? FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 240) : null; - if (!(thumb instanceof TLRPC.TL_photoSize) && !(thumb instanceof TLRPC.TL_photoSizeProgressive)) { - thumb = null; - } - String artworkUrl = messageObject.getArtworkUrl(false); - if (!TextUtils.isEmpty(artworkUrl)) { - if (thumb != null) { - placeholderImageView.setImage(ImageLocation.getForPath(artworkUrl), null, ImageLocation.getForDocument(thumb, document), null, null, 0, 1, messageObject); - } else { - placeholderImageView.setImage(artworkUrl, null, null); - } - } else if (thumb != null) { - placeholderImageView.setImage(null, null, ImageLocation.getForDocument(thumb, document), null, null, 0, 1, messageObject); - } else { - placeholderImageView.setImageDrawable(null); - } - placeholderImageView.invalidate(); - } - int duration = lastDuration = messageObject.getDuration(); if (durationTextView != null) { @@ -1485,6 +1530,91 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } else { playbackSpeedButton.setVisibility(View.GONE); } + + if (!sameMessageObject) { + preloadNeighboringThumbs(); + } + } + } + + private void updateCover(MessageObject messageObject, boolean animated) { + final BackupImageView imageView = animated ? coverContainer.getNextImageView() : coverContainer.getImageView(); + final AudioInfo audioInfo = MediaController.getInstance().getAudioInfo(); + if (audioInfo != null && audioInfo.getCover() != null) { + imageView.setImageBitmap(audioInfo.getCover()); + currentFile = null; + currentAudioFinishedLoading = true; + } else { + TLRPC.Document document = messageObject.getDocument(); + currentFile = FileLoader.getAttachFileName(document); + currentAudioFinishedLoading = false; + String artworkUrl = messageObject.getArtworkUrl(false); + final ImageLocation thumbImageLocation = getArtworkThumbImageLocation(messageObject); + if (!TextUtils.isEmpty(artworkUrl)) { + imageView.setImage(ImageLocation.getForPath(artworkUrl), null, thumbImageLocation, null, null, 0, 1, messageObject); + } else if (thumbImageLocation != null) { + imageView.setImage(null, null, thumbImageLocation, null, null, 0, 1, messageObject); + } else { + imageView.setImageDrawable(null); + } + imageView.invalidate(); + } + if (animated) { + coverContainer.switchImageViews(); + } + } + + private ImageLocation getArtworkThumbImageLocation(MessageObject messageObject) { + final TLRPC.Document document = messageObject.getDocument(); + TLRPC.PhotoSize thumb = document != null ? FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 240) : null; + if (!(thumb instanceof TLRPC.TL_photoSize) && !(thumb instanceof TLRPC.TL_photoSizeProgressive)) { + thumb = null; + } + if (thumb != null) { + return ImageLocation.getForDocument(thumb, document); + } else { + final String smallArtworkUrl = messageObject.getArtworkUrl(true); + if (smallArtworkUrl != null) { + return ImageLocation.getForPath(smallArtworkUrl); + } + } + return null; + } + + private void preloadNeighboringThumbs() { + final MediaController mediaController = MediaController.getInstance(); + final List playlist = mediaController.getPlaylist(); + if (playlist.size() <= 1) { + return; + } + + final List neighboringItems = new ArrayList<>(); + final int playingIndex = mediaController.getPlayingMessageObjectNum(); + + int nextIndex = playingIndex + 1; + int prevIndex = playingIndex - 1; + if (nextIndex >= playlist.size()) { + nextIndex = 0; + } + if (prevIndex <= -1) { + prevIndex = playlist.size() - 1; + } + + neighboringItems.add(playlist.get(nextIndex)); + if (nextIndex != prevIndex) { + neighboringItems.add(playlist.get(prevIndex)); + } + + for (int i = 0, N = neighboringItems.size(); i < N; i++) { + final MessageObject messageObject = neighboringItems.get(i); + final ImageLocation thumbImageLocation = getArtworkThumbImageLocation(messageObject); + if (thumbImageLocation != null) { + if (thumbImageLocation.path != null) { + ImageLoader.getInstance().preloadArtwork(thumbImageLocation.path); + } else { + FileLoader.getInstance(currentAccount).loadFile(thumbImageLocation, messageObject, null, 0, 1); + } + } } } @@ -1693,8 +1823,8 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_player_progressBackground)); themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_player_progress)); themeDescriptions.add(new ThemeDescription(seekBarView, 0, null, null, null, null, Theme.key_player_progressBackground)); - themeDescriptions.add(new ThemeDescription(seekBarView, 0, null, null, null, null, Theme.key_player_progress)); themeDescriptions.add(new ThemeDescription(seekBarView, 0, null, null, null, null, Theme.key_player_progressCachedBackground)); + themeDescriptions.add(new ThemeDescription(seekBarView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_player_progress)); themeDescriptions.add(new ThemeDescription(playbackSpeedButton, ThemeDescription.FLAG_CHECKTAG | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_inappPlayerPlayPause)); themeDescriptions.add(new ThemeDescription(playbackSpeedButton, ThemeDescription.FLAG_CHECKTAG | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_inappPlayerClose)); @@ -1709,13 +1839,17 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. themeDescriptions.add(new ThemeDescription(optionsButton, 0, null, null, null, delegate, Theme.key_actionBarDefaultSubmenuItem)); themeDescriptions.add(new ThemeDescription(optionsButton, 0, null, null, null, delegate, Theme.key_actionBarDefaultSubmenuBackground)); - themeDescriptions.add(new ThemeDescription(prevButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(prevButton, 0, null, new RLottieDrawable[]{prevButton.getAnimatedDrawable()}, "Triangle 3", Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(prevButton, 0, null, new RLottieDrawable[]{prevButton.getAnimatedDrawable()}, "Triangle 4", Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(prevButton, 0, null, new RLottieDrawable[]{prevButton.getAnimatedDrawable()}, "Rectangle 4", Theme.key_player_button)); themeDescriptions.add(new ThemeDescription(prevButton, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(playButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_player_button)); themeDescriptions.add(new ThemeDescription(playButton, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, null, null, null, null, Theme.key_listSelector)); - themeDescriptions.add(new ThemeDescription(nextButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(nextButton, 0, null, new RLottieDrawable[]{nextButton.getAnimatedDrawable()}, "Triangle 3", Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(nextButton, 0, null, new RLottieDrawable[]{nextButton.getAnimatedDrawable()}, "Triangle 4", Theme.key_player_button)); + themeDescriptions.add(new ThemeDescription(nextButton, 0, null, new RLottieDrawable[]{nextButton.getAnimatedDrawable()}, "Rectangle 4", Theme.key_player_button)); themeDescriptions.add(new ThemeDescription(nextButton, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(playerLayout, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_player_background)); @@ -1736,11 +1870,250 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. themeDescriptions.add(new ThemeDescription(durationTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_time)); themeDescriptions.add(new ThemeDescription(timeTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_time)); - themeDescriptions.add(new ThemeDescription(titleTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_actionBarTitle)); - themeDescriptions.add(new ThemeDescription(authorTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_time)); + themeDescriptions.add(new ThemeDescription(titleTextView.getTextView(), ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_actionBarTitle)); + themeDescriptions.add(new ThemeDescription(titleTextView.getNextTextView(), ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_actionBarTitle)); + themeDescriptions.add(new ThemeDescription(authorTextView.getTextView(), ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_time)); + themeDescriptions.add(new ThemeDescription(authorTextView.getNextTextView(), ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_time)); themeDescriptions.add(new ThemeDescription(containerView, 0, null, null, null, null, Theme.key_sheet_scrollUp)); return themeDescriptions; } + + private static abstract class CoverContainer extends FrameLayout { + + private final BackupImageView[] imageViews = new BackupImageView[2]; + + private int activeIndex; + private AnimatorSet animatorSet; + + public CoverContainer(@NonNull Context context) { + super(context); + for (int i = 0; i < 2; i++) { + imageViews[i] = new BackupImageView(context); + final int index = i; + imageViews[i].getImageReceiver().setDelegate((imageReceiver, set, thumb, memCache) -> { + if (index == activeIndex) { + onImageUpdated(imageReceiver); + } + }); + imageViews[i].setRoundRadius(AndroidUtilities.dp(4)); + if (i == 1) { + imageViews[i].setVisibility(GONE); + } + addView(imageViews[i], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } + } + + public final void switchImageViews() { + if (animatorSet != null) { + animatorSet.cancel(); + } + animatorSet = new AnimatorSet(); + activeIndex = activeIndex == 0 ? 1 : 0; + + final BackupImageView prevImageView = imageViews[activeIndex == 0 ? 1 : 0]; + final BackupImageView currImageView = imageViews[activeIndex]; + + final boolean hasBitmapImage = prevImageView.getImageReceiver().hasBitmapImage(); + + currImageView.setAlpha(hasBitmapImage ? 1f : 0f); + currImageView.setScaleX(0.8f); + currImageView.setScaleY(0.8f); + currImageView.setVisibility(VISIBLE); + + if (hasBitmapImage) { + prevImageView.bringToFront(); + } else { + prevImageView.setVisibility(GONE); + prevImageView.setImageDrawable(null); + } + + final ValueAnimator expandAnimator = ValueAnimator.ofFloat(0.8f, 1f); + expandAnimator.setDuration(125); + expandAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT); + expandAnimator.addUpdateListener(a -> { + float animatedValue = (float) a.getAnimatedValue(); + currImageView.setScaleX(animatedValue); + currImageView.setScaleY(animatedValue); + if (!hasBitmapImage) { + currImageView.setAlpha(a.getAnimatedFraction()); + } + }); + + if (hasBitmapImage) { + final ValueAnimator collapseAnimator = ValueAnimator.ofFloat(prevImageView.getScaleX(), 0.8f); + collapseAnimator.setDuration(125); + collapseAnimator.setInterpolator(CubicBezierInterpolator.EASE_IN); + collapseAnimator.addUpdateListener(a -> { + float animatedValue = (float) a.getAnimatedValue(); + prevImageView.setScaleX(animatedValue); + prevImageView.setScaleY(animatedValue); + final float fraction = a.getAnimatedFraction(); + if (fraction > 0.25f && !currImageView.getImageReceiver().hasBitmapImage()) { + prevImageView.setAlpha(1f - (fraction - 0.25f) * (1f / 0.75f)); + } + }); + collapseAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + prevImageView.setVisibility(GONE); + prevImageView.setImageDrawable(null); + prevImageView.setAlpha(1f); + } + }); + + animatorSet.playSequentially(collapseAnimator, expandAnimator); + } else { + animatorSet.play(expandAnimator); + } + + animatorSet.start(); + } + + public final BackupImageView getImageView() { + return imageViews[activeIndex]; + } + + public final BackupImageView getNextImageView() { + return imageViews[activeIndex == 0 ? 1 : 0]; + } + + public final ImageReceiver getImageReceiver() { + return getImageView().getImageReceiver(); + } + + protected abstract void onImageUpdated(ImageReceiver imageReceiver); + } + + private abstract static class ClippingTextViewSwitcher extends FrameLayout { + + private final TextView[] textViews = new TextView[2]; + private final float[] clipProgress = new float[]{0f, 0.75f}; + private final int gradientSize = AndroidUtilities.dp(24); + + private final Matrix gradientMatrix; + private final Paint gradientPaint; + private final Paint erasePaint; + + private int activeIndex; + private AnimatorSet animatorSet; + private LinearGradient gradientShader; + + public ClippingTextViewSwitcher(@NonNull Context context) { + super(context); + for (int i = 0; i < 2; i++) { + textViews[i] = createTextView(); + if (i == 1) { + textViews[i].setAlpha(0f); + textViews[i].setVisibility(GONE); + } + addView(textViews[i], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); + } + gradientMatrix = new Matrix(); + gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + gradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + erasePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + gradientShader = new LinearGradient(gradientSize, 0, 0, 0, 0, 0xFF000000, Shader.TileMode.CLAMP); + gradientPaint.setShader(gradientShader); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + final int index = child == textViews[0] ? 0 : 1; + final boolean result; + if (clipProgress[index] > 0f) { + final int width = child.getWidth(); + final int height = child.getHeight(); + final int saveCount = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG); + result = super.drawChild(canvas, child, drawingTime); + final float gradientStart = width * (1f - clipProgress[index]); + final float gradientEnd = gradientStart + gradientSize; + gradientMatrix.setTranslate(gradientStart, 0); + gradientShader.setLocalMatrix(gradientMatrix); + canvas.drawRect(gradientStart, 0, gradientEnd, height, gradientPaint); + if (width > gradientEnd) { + canvas.drawRect(gradientEnd, 0, width, height, erasePaint); + } + canvas.restoreToCount(saveCount); + } else { + result = super.drawChild(canvas, child, drawingTime); + } + return result; + } + + public void setText(CharSequence text) { + final CharSequence currentText = textViews[activeIndex].getText(); + + if (TextUtils.isEmpty(currentText)) { + textViews[activeIndex].setText(text); + return; + } else if (TextUtils.equals(text, currentText)) { + return; + } + + final int index = activeIndex == 0 ? 1 : 0; + final int prevIndex = activeIndex; + activeIndex = index; + + if (animatorSet != null) { + animatorSet.cancel(); + } + animatorSet = new AnimatorSet(); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + textViews[prevIndex].setVisibility(GONE); + } + }); + + textViews[index].setText(text); + textViews[index].bringToFront(); + textViews[index].setVisibility(VISIBLE); + + final int duration = 300; + + final ValueAnimator collapseAnimator = ValueAnimator.ofFloat(clipProgress[prevIndex], 0.75f); + collapseAnimator.setDuration(duration / 3 * 2); // 0.66 + collapseAnimator.addUpdateListener(a -> { + clipProgress[prevIndex] = (float) a.getAnimatedValue(); + invalidate(); + }); + + final ValueAnimator expandAnimator = ValueAnimator.ofFloat(clipProgress[index], 0f); + expandAnimator.setStartDelay(duration / 3); // 0.33 + expandAnimator.setDuration(duration / 3 * 2); // 0.66 + expandAnimator.addUpdateListener(a -> { + clipProgress[index] = (float) a.getAnimatedValue(); + invalidate(); + }); + + final ObjectAnimator fadeOutAnimator = ObjectAnimator.ofFloat(textViews[prevIndex], View.ALPHA, 0f); + fadeOutAnimator.setStartDelay(duration / 4); // 0.25 + fadeOutAnimator.setDuration(duration / 2); // 0.5 + + final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(textViews[index], View.ALPHA, 1f); + fadeInAnimator.setStartDelay(duration / 4); // 0.25 + fadeInAnimator.setDuration(duration / 2); // 0.5 + + animatorSet.playTogether(collapseAnimator, expandAnimator, fadeOutAnimator, fadeInAnimator); + animatorSet.start(); + } + + public TextView getTextView() { + return textViews[activeIndex]; + } + + public TextView getNextTextView() { + return textViews[activeIndex == 0 ? 1 : 0]; + } + + protected abstract TextView createTextView(); + } } \ No newline at end of file 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 fe1177d46..a8e91cd69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -13,6 +13,7 @@ import android.graphics.Typeface; import android.graphics.drawable.InsetDrawable; import android.os.Build; import android.util.TypedValue; +import android.view.GestureDetector; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -30,8 +31,10 @@ import androidx.core.util.Preconditions; import androidx.core.view.ViewCompat; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.dynamicanimation.animation.SpringForce; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.BaseFragment; @@ -81,25 +84,33 @@ public final class Bulletin { private static Bulletin visibleBulletin; private final Layout layout; - private final FrameLayout parentLayout; + private final ParentLayout parentLayout; private final FrameLayout containerLayout; + private final Runnable hideRunnable = this::hide; private final int duration; private boolean showing; - private Runnable exitRunnable; + private boolean canHide; private int currentBottomOffset; private Delegate currentDelegate; private Layout.Transition layoutTransition; private Bulletin(@NonNull FrameLayout containerLayout, @NonNull Layout layout, int duration) { this.layout = layout; - this.parentLayout = new FrameLayout(layout.getContext()); - this.parentLayout.addView(layout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + this.parentLayout = new ParentLayout(layout) { + @Override + protected void onPressedStateChanged(boolean pressed) { + setCanHide(!pressed); + if (containerLayout.getParent() != null) { + containerLayout.getParent().requestDisallowInterceptTouchEvent(pressed); + } + } + }; this.containerLayout = containerLayout; this.duration = duration; } - public void show() { + public Bulletin show() { if (!showing) { showing = true; @@ -128,7 +139,7 @@ public final class Bulletin { ensureLayoutTransitionCreated(); layoutTransition.animateEnter(layout, layout::onEnterTransitionStart, () -> { layout.onEnterTransitionEnd(); - layout.postDelayed(exitRunnable = Bulletin.this::hide, duration); + setCanHide(true); }, offset -> { if (currentDelegate != null) { currentDelegate.onOffsetChange(layout.getHeight() - offset); @@ -141,7 +152,7 @@ public final class Bulletin { layout.setTranslationY(-currentBottomOffset); layout.onEnterTransitionStart(); layout.onEnterTransitionEnd(); - layout.postDelayed(exitRunnable = Bulletin.this::hide, duration); + setCanHide(true); } } } @@ -160,6 +171,18 @@ public final class Bulletin { containerLayout.addView(parentLayout); } + return this; + } + + private void setCanHide(boolean canHide) { + if (this.canHide != canHide) { + this.canHide = canHide; + if (canHide) { + layout.postDelayed(hideRunnable, duration); + } else { + layout.removeCallbacks(hideRunnable); + } + } } private void ensureLayoutTransitionCreated() { @@ -172,8 +195,8 @@ public final class Bulletin { hide(isTransitionsEnabled()); } - private void hide(boolean animated) { - if (showing) { + public void hide(boolean animated) { + if (showing && canHide) { showing = false; if (visibleBulletin == this) { @@ -184,10 +207,7 @@ public final class Bulletin { currentBottomOffset = 0; if (ViewCompat.isLaidOut(layout)) { - if (exitRunnable != null) { - layout.removeCallbacks(exitRunnable); - exitRunnable = null; - } + layout.removeCallbacks(hideRunnable); if (animated) { ensureLayoutTransitionCreated(); layoutTransition.animateExit(layout, layout::onExitTransitionStart, () -> { @@ -232,6 +252,85 @@ public final class Bulletin { return MessagesController.getGlobalMainSettings().getBoolean("view_animations", true) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; } + private static abstract class ParentLayout extends FrameLayout { + + private final Layout layout; + private final Rect rect = new Rect(); + private final GestureDetector gestureDetector; + + private boolean pressed; + private float translationX; + private SpringAnimation springAnimation; + + public ParentLayout(Layout layout) { + super(layout.getContext()); + this.layout = layout; + gestureDetector = new GestureDetector(layout.getContext(), new GestureDetector.SimpleOnGestureListener() { + + @Override + public boolean onDown(MotionEvent e) { + return springAnimation == null; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + layout.setTranslationX(translationX -= distanceX); + return true; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (Math.abs(velocityX) > 2000f) { + springAnimation = new SpringAnimation(layout, DynamicAnimation.TRANSLATION_X, Math.signum(velocityX) * layout.getWidth() * 2f); + springAnimation.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY); + springAnimation.getSpring().setStiffness(100f); + springAnimation.setStartVelocity(velocityX); + springAnimation.start(); + return true; + } + return false; + } + }); + gestureDetector.setIsLongpressEnabled(false); + addView(layout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (pressed || inLayoutHitRect(event.getX(), event.getY())) { + gestureDetector.onTouchEvent(event); + final int actionMasked = event.getActionMasked(); + if (actionMasked == MotionEvent.ACTION_DOWN) { + if (!pressed && springAnimation == null) { + layout.animate().cancel(); + translationX = layout.getTranslationX(); + onPressedStateChanged(pressed = true); + } + } else if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL) { + if (pressed) { + if (springAnimation == null) { + if (Math.abs(translationX) > layout.getWidth() / 2) { + layout.animate().translationX(Math.signum(translationX) * layout.getWidth()).setDuration(200).setInterpolator(AndroidUtilities.accelerateInterpolator).start(); + } else { + layout.animate().translationX(0).setDuration(200).start(); + } + } + onPressedStateChanged(pressed = false); + } + } + return true; + } + return false; + } + + private boolean inLayoutHitRect(float x, float y) { + layout.getHitRect(rect); + return rect.contains((int) x, (int) y); + } + + protected abstract void onPressedStateChanged(boolean pressed); + } + //region Offset Providers public static void addDelegate(@NonNull BaseFragment fragment, @NonNull Delegate delegate) { final FrameLayout containerLayout = fragment.getLayoutContainer(); @@ -297,12 +396,6 @@ public final class Bulletin { setLayoutParams(LayoutHelper.createFrame(matchParentWidth ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL)); } - @Override - public boolean onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - return true; - } - public Bulletin getBulletin() { return bulletin; } @@ -481,22 +574,14 @@ public final class Bulletin { springAnimation.getSpring().setDampingRatio(DAMPING_RATIO); springAnimation.getSpring().setStiffness(STIFFNESS); if (endAction != null) { - springAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() { - @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, float velocity) { - if (!canceled) { - endAction.run(); - } + springAnimation.addEndListener((animation, canceled, value, velocity) -> { + if (!canceled) { + endAction.run(); } }); } if (onUpdate != null) { - springAnimation.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { - @Override - public void onAnimationUpdate(DynamicAnimation animation, float value, float velocity) { - onUpdate.accept(value); - } - }); + springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(value)); } springAnimation.start(); if (startAction != null) { @@ -510,22 +595,14 @@ public final class Bulletin { springAnimation.getSpring().setDampingRatio(DAMPING_RATIO); springAnimation.getSpring().setStiffness(STIFFNESS); if (endAction != null) { - springAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() { - @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, float velocity) { - if (!canceled) { - endAction.run(); - } + springAnimation.addEndListener((animation, canceled, value, velocity) -> { + if (!canceled) { + endAction.run(); } }); } if (onUpdate != null) { - springAnimation.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { - @Override - public void onAnimationUpdate(DynamicAnimation animation, float value, float velocity) { - onUpdate.accept(value); - } - }); + springAnimation.addUpdateListener((animation, value, velocity) -> onUpdate.accept(value)); } springAnimation.start(); if (startAction != null) { @@ -644,6 +721,61 @@ public final class Bulletin { subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); linearLayout.addView(subtitleTextView); } + + } + + public static class TwoLineLottieLayout extends ButtonLayout { + + public final RLottieImageView imageView; + public final TextView titleTextView; + public final TextView subtitleTextView; + + private final int textColor; + + public TwoLineLottieLayout(@NonNull Context context) { + this(context, Theme.getColor(Theme.key_undo_background), Theme.getColor(Theme.key_undo_infoColor)); + } + + public TwoLineLottieLayout(@NonNull Context context, @ColorInt int backgroundColor, @ColorInt int textColor) { + super(context, backgroundColor); + this.textColor = textColor; + + imageView = new RLottieImageView(context); + addView(imageView, LayoutHelper.createFrameRelatively(28, 28, Gravity.START | Gravity.CENTER_VERTICAL, 14, 10, 14, 10)); + + final int undoInfoColor = Theme.getColor(Theme.key_undo_infoColor); + + final LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + addView(linearLayout, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 54, 8, 12, 8)); + + titleTextView = new TextView(context); + titleTextView.setSingleLine(); + titleTextView.setTextColor(undoInfoColor); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + linearLayout.addView(titleTextView); + + subtitleTextView = new TextView(context); + subtitleTextView.setMaxLines(2); + subtitleTextView.setTextColor(undoInfoColor); + subtitleTextView.setTypeface(Typeface.SANS_SERIF); + subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + linearLayout.addView(subtitleTextView); + } + + @Override + protected void onShow() { + super.onShow(); + imageView.playAnimation(); + } + + public void setAnimation(int resId, String... layers) { + imageView.setAnimation(resId, 28, 28); + for (int i = 0; i < layers.length; i++) { + imageView.setLayerColor(layers[i] + ".**", textColor); + } + } } public static class LottieLayout extends ButtonLayout { @@ -736,18 +868,31 @@ public final class Bulletin { private Bulletin bulletin; private boolean isUndone; - public UndoButton(@NonNull Context context) { + public UndoButton(@NonNull Context context, boolean text) { super(context); final int undoCancelColor = Theme.getColor(Theme.key_undo_cancelColor); - final ImageView undoImageView = new ImageView(getContext()); - undoImageView.setOnClickListener(v -> undo()); - undoImageView.setImageResource(R.drawable.chats_undo); - undoImageView.setColorFilter(new PorterDuffColorFilter(undoCancelColor, PorterDuff.Mode.MULTIPLY)); - undoImageView.setBackground(Theme.createSelectorDrawable((undoCancelColor & 0x00ffffff) | 0x19000000)); - ViewHelper.setPaddingRelative(undoImageView, 0, 12, 0, 12); - addView(undoImageView, LayoutHelper.createFrameRelatively(56, 48, Gravity.CENTER_VERTICAL)); + if (text) { + TextView undoTextView = new TextView(context); + undoTextView.setOnClickListener(v -> undo()); + undoTextView.setBackground(Theme.createSelectorDrawable((undoCancelColor & 0x00ffffff) | 0x19000000, 7)); + undoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + undoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + undoTextView.setTextColor(undoCancelColor); + undoTextView.setText(LocaleController.getString("Undo", R.string.Undo)); + undoTextView.setGravity(Gravity.CENTER_VERTICAL); + ViewHelper.setPaddingRelative(undoTextView, 16, 0, 16, 0); + addView(undoTextView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 48, Gravity.CENTER_VERTICAL, 0, 0, 0, 0)); + } else { + final ImageView undoImageView = new ImageView(getContext()); + undoImageView.setOnClickListener(v -> undo()); + undoImageView.setImageResource(R.drawable.chats_undo); + undoImageView.setColorFilter(new PorterDuffColorFilter(undoCancelColor, PorterDuff.Mode.MULTIPLY)); + undoImageView.setBackground(Theme.createSelectorDrawable((undoCancelColor & 0x00ffffff) | 0x19000000)); + ViewHelper.setPaddingRelative(undoImageView, 0, 12, 0, 12); + addView(undoImageView, LayoutHelper.createFrameRelatively(56, 48, Gravity.CENTER_VERTICAL)); + } } public void undo() { 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 896683316..05d34a448 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -1,9 +1,11 @@ package org.telegram.ui.Components; +import android.content.Context; import android.widget.FrameLayout; import androidx.core.util.Preconditions; +import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; @@ -11,13 +13,112 @@ import org.telegram.ui.ActionBar.BaseFragment; public final class BulletinFactory { - private BulletinFactory() { + public static BulletinFactory of(BaseFragment fragment) { + Preconditions.checkNotNull(fragment); + return new BulletinFactory(fragment); + } + + public static BulletinFactory of(FrameLayout containerLayout) { + Preconditions.checkNotNull(containerLayout); + return new BulletinFactory(containerLayout); } public static boolean canShowBulletin(BaseFragment fragment) { - return fragment != null && fragment.getParentActivity() != null; + return fragment != null && fragment.getParentActivity() != null && fragment.getLayoutContainer() != null; } + public enum FileType { + PHOTO("PhotoSavedHint", R.string.PhotoSavedHint), + PHOTO_TO_DOWNLOADS("PhotoSavedToDownloadsHint", R.string.PhotoSavedToDownloadsHint), + PHOTOS("PhotosSavedHint"), + + VIDEO("VideoSavedHint", R.string.VideoSavedHint), + VIDEO_TO_DOWNLOADS("VideoSavedToDownloadsHint", R.string.VideoSavedToDownloadsHint), + VIDEOS("VideosSavedHint"), + + AUDIO("AudioSavedHint", R.string.AudioSavedHint), + AUDIOS("AudiosSavedHint"), + GIF("GifSavedToDownloadsHint", R.string.GifSavedToDownloadsHint), + MEDIA("MediaSavedHint"), + + UNKNOWN("FileSavedHint", R.string.FileSavedHint), + UNKNOWNS("FilesSavedHint"); + + private final String localeKey; + private final int localeRes; + private final boolean plural; + + FileType(String localeKey, int localeRes) { + this.localeKey = localeKey; + this.localeRes = localeRes; + this.plural = false; + } + + FileType(String localeKey) { + this.localeKey = localeKey; + this.localeRes = 0; + this.plural = true; + } + + private String getText() { + return getText(1); + } + + private String getText(int amount) { + if (plural) { + return LocaleController.formatPluralString(localeKey, amount); + } else { + return LocaleController.getString(localeKey, localeRes); + } + } + } + + private final BaseFragment fragment; + private final FrameLayout containerLayout; + + private BulletinFactory(BaseFragment fragment) { + this.fragment = fragment; + this.containerLayout = null; + } + + private BulletinFactory(FrameLayout containerLayout) { + this.containerLayout = containerLayout; + this.fragment = null; + } + + public Bulletin createDownloadBulletin(FileType fileType) { + return createDownloadBulletin(fileType, 1); + } + + public Bulletin createDownloadBulletin(FileType fileType, int filesAmount) { + return createDownloadBulletin(fileType, filesAmount, 0, 0); + } + + public Bulletin createDownloadBulletin(FileType fileType, int filesAmount, int backgroundColor, int textColor) { + final Bulletin.LottieLayout layout; + if (backgroundColor != 0 && textColor != 0) { + layout = new Bulletin.LottieLayout(getContext(), backgroundColor, textColor); + } else { + layout = new Bulletin.LottieLayout(getContext()); + } + layout.setAnimation(R.raw.ic_download, "Box", "Arrow", "Mask", "Arrow 2", "Splash"); + layout.textView.setText(fileType.getText(filesAmount)); + return create(layout, Bulletin.DURATION_SHORT); + } + + private Bulletin create(Bulletin.Layout layout, int duration) { + if (fragment != null) { + return Bulletin.make(fragment, layout, duration); + } else { + return Bulletin.make(containerLayout, layout, duration); + } + } + + private Context getContext() { + return fragment != null ? fragment.getParentActivity() : containerLayout.getContext(); + } + + //region Static Factory public static Bulletin createMuteBulletin(BaseFragment fragment, int setting) { Preconditions.checkArgument(canShowBulletin(fragment)); final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity()); @@ -72,16 +173,58 @@ public final class BulletinFactory { return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); } - public static Bulletin createSaveToGalleryBulletin(FrameLayout containerLayout, boolean video, int backgroundColor, int textColor) { - Preconditions.checkNotNull(containerLayout); - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(containerLayout.getContext(), backgroundColor, textColor); - layout.imageView.setAnimation(R.raw.ic_download, 28, 28); - layout.setAnimation(R.raw.ic_download, "Box", "Arrow", "Mask", "Arrow 2", "Splash"); - if (video) { - layout.textView.setText(LocaleController.getString("VideoSavedHint", R.string.VideoSavedHint)); + public static Bulletin createUnpinAllMessagesBulletin(BaseFragment fragment, int count, boolean hide, Runnable undoAction, Runnable delayedAction) { + Preconditions.checkArgument(canShowBulletin(fragment)); + Bulletin.ButtonLayout buttonLayout; + if (hide) { + final Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(fragment.getParentActivity()); + layout.setAnimation(R.raw.ic_unpin, "Pin", "Line"); + layout.titleTextView.setText(LocaleController.getString("PinnedMessagesHidden", R.string.PinnedMessagesHidden)); + layout.subtitleTextView.setText(LocaleController.getString("PinnedMessagesHiddenInfo", R.string.PinnedMessagesHiddenInfo)); + buttonLayout = layout; } else { - layout.textView.setText(LocaleController.getString("PhotoSavedHint", R.string.PhotoSavedHint)); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity()); + layout.setAnimation(R.raw.ic_unpin, "Pin", "Line"); + layout.textView.setText(LocaleController.formatPluralString("MessagesUnpinned", count)); + buttonLayout = layout; } - return Bulletin.make(containerLayout, layout, Bulletin.DURATION_SHORT); + buttonLayout.setButton(new Bulletin.UndoButton(fragment.getParentActivity(), true).setUndoAction(undoAction).setDelayedAction(delayedAction)); + return Bulletin.make(fragment, buttonLayout, 5000); } + + public static Bulletin createSaveToGalleryBulletin(BaseFragment fragment, boolean video) { + return of(fragment).createDownloadBulletin(video ? FileType.VIDEO : FileType.PHOTO); + } + + public static Bulletin createSaveToGalleryBulletin(FrameLayout containerLayout, boolean video, int backgroundColor, int textColor) { + return of(containerLayout).createDownloadBulletin(video ? FileType.VIDEO : FileType.PHOTO, 1, backgroundColor, textColor); + } + + public static Bulletin createPromoteToAdminBulletin(BaseFragment fragment, String userFirstName) { + Preconditions.checkArgument(canShowBulletin(fragment)); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity()); + layout.setAnimation(R.raw.ic_admin, "Shield"); + layout.textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("UserSetAsAdminHint", R.string.UserSetAsAdminHint, userFirstName))); + return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); + } + + public static Bulletin createPinMessageBulletin(BaseFragment fragment) { + return createPinMessageBulletin(fragment, true, null, null); + } + + public static Bulletin createUnpinMessageBulletin(BaseFragment fragment, Runnable undoAction, Runnable delayedAction) { + return createPinMessageBulletin(fragment, false, undoAction, delayedAction); + } + + private static Bulletin createPinMessageBulletin(BaseFragment fragment, boolean pinned, Runnable undoAction, Runnable delayedAction) { + Preconditions.checkArgument(canShowBulletin(fragment)); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity()); + layout.setAnimation(pinned ? R.raw.ic_pin : R.raw.ic_unpin, "Pin", "Line"); + layout.textView.setText(LocaleController.getString(pinned ? "MessagePinnedHint" : "MessageUnpinnedHint", pinned ? R.string.MessagePinnedHint : R.string.MessageUnpinnedHint)); + if (!pinned) { + layout.setButton(new Bulletin.UndoButton(fragment.getParentActivity(), true).setUndoAction(undoAction).setDelayedAction(delayedAction)); + } + return Bulletin.make(fragment, layout, pinned ? Bulletin.DURATION_SHORT : 5000); + } + //endregion } 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 533bef170..5d7f2acd6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -46,6 +46,7 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.ImageSpan; import android.util.Property; @@ -133,6 +134,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private boolean clearBotButtonsOnKeyboardOpen; private boolean expandStickersWithKeyboard; + public int getHeightWithTopView() { + int h = getMeasuredHeight(); + if (topView != null && topView.getVisibility() == View.VISIBLE) { + h -= (1f - topViewEnterProgress) * topView.getLayoutParams().height; + } + return h; + } + public interface ChatActivityEnterViewDelegate { void onMessageSend(CharSequence message, boolean notify, int scheduleDate); @@ -195,6 +204,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe default void prepareMessageSending() { } + + default void onTrendingStickersShowed(boolean show) { + + } } private final static int RECORD_STATE_ENTER = 0; @@ -459,16 +472,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe boolean prevOpen2 = emojiTabOpen; emojiTabOpen = curPage == 0; if (stickersExpanded) { - if (!stickersTabOpen && searchingType == 0) { - if (searchingType != 0) { - searchingType = 0; - emojiView.closeSearch(true); - emojiView.hideSearchKeyboard(); - } - setStickersExpanded(false, true, false); - } else if (searchingType != 0) { + if (searchingType != 0) { searchingType = curPage == 0 ? 2 : 1; checkStickresExpandHeight(); + } else if (!stickersTabOpen) { + setStickersExpanded(false, true, false); } } if (prevOpen != stickersTabOpen || prevOpen2 != emojiTabOpen) { @@ -2019,6 +2027,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe @Override public boolean onTouchEvent(MotionEvent event) { + if (stickersDragging || stickersExpansionAnim != null) { + return false; + } if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { if (searchingType != 0) { searchingType = 0; @@ -2154,9 +2165,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if ((ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && editingMessageObject == null) { sendMessage(); return true; - } else if (i == KeyEvent.KEYCODE_CTRL_LEFT || i == KeyEvent.KEYCODE_CTRL_RIGHT) { - ctrlPressed = keyEvent.getAction() == KeyEvent.ACTION_DOWN; - return true; } } return false; @@ -2191,7 +2199,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe CharSequence message = AndroidUtilities.getTrimmedString(charSequence.toString()); if (delegate != null) { if (!ignoreTextChange) { - if (count > 2 || charSequence == null || charSequence.length() == 0) { + if (count > 2 || TextUtils.isEmpty(charSequence)) { messageWebPageSearch = true; } delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2); @@ -2201,14 +2209,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe processChange = true; } if (editingMessageObject == null && !canWriteToChannel && message.length() != 0 && lastTypingTimeSend < System.currentTimeMillis() - 5000 && !ignoreTextChange) { - int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - TLRPC.User currentUser = null; - if ((int) dialog_id > 0) { - currentUser = accountInstance.getMessagesController().getUser((int) dialog_id); - } - if (currentUser != null && (currentUser.id == UserConfig.getInstance(currentAccount).getClientUserId() || currentUser.status != null && currentUser.status.expires < currentTime && !accountInstance.getMessagesController().onlinePrivacy.containsKey(currentUser.id))) { - return; - } lastTypingTimeSend = System.currentTimeMillis(); if (delegate != null) { delegate.needSendTyping(); @@ -2289,7 +2289,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); preferences1.edit().remove("hidekeyboard_" + dialog_id).commit(); } else { - if (currentPopupContentType == 1 && botButtonsMessageObject != null) { + if (botButtonsMessageObject != null) { SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); preferences1.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); } @@ -2874,7 +2874,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } sendButtonContainer.addView(expandStickersButton, LayoutHelper.createFrame(48, 48)); expandStickersButton.setOnClickListener(v -> { - if (expandStickersButton.getVisibility() != VISIBLE || expandStickersButton.getAlpha() != 1.0f) { + if (expandStickersButton.getVisibility() != VISIBLE || expandStickersButton.getAlpha() != 1.0f || waitingForKeyboardOpen || (keyboardVisible && messageEditText.isFocused())) { return; } if (stickersExpanded) { @@ -3050,7 +3050,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } else { cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); } - } else if (num == 1) { + } else { cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } cell.setMinimumWidth(AndroidUtilities.dp(196)); @@ -3061,7 +3061,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } if (num == 0) { AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), this::sendMessageInternal); - } else if (num == 1) { + } else { sendMessageInternal(false, 0); } }); @@ -3795,12 +3795,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } replyingMessageObject = messageObject; setButtons(replyingMessageObject, true); - } else if (messageObject == null && replyingMessageObject == botButtonsMessageObject) { + } else if (replyingMessageObject == botButtonsMessageObject) { replyingMessageObject = null; setButtons(botMessageObject, false); botMessageObject = null; } else { - replyingMessageObject = messageObject; + replyingMessageObject = null; } MediaController.getInstance().setReplyingMessage(messageObject, getThreadMessage()); } @@ -4463,7 +4463,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe runningAnimation2 = null; } - if (attachLayout != null || recordInterfaceState == 0) { + if (attachLayout != null && recordInterfaceState == 0) { attachLayout.setVisibility(VISIBLE); runningAnimation2 = new AnimatorSet(); ArrayList animators = new ArrayList<>(); @@ -5802,12 +5802,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (AndroidUtilities.isTablet()) { if (parentActivity instanceof LaunchActivity) { LaunchActivity launchActivity = (LaunchActivity) parentActivity; - if (launchActivity != null) { - View layout = launchActivity.getLayersActionBarLayout(); - allowFocus = layout == null || layout.getVisibility() != View.VISIBLE; - } else { - allowFocus = true; - } + View layout = launchActivity.getLayersActionBarLayout(); + allowFocus = layout == null || layout.getVisibility() != View.VISIBLE; } else { allowFocus = true; } @@ -5886,11 +5882,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe scheduledButton.setAlpha(visible ? 1.0f : 0.0f); scheduledButton.setScaleX(visible ? 1.0f : 0.1f); scheduledButton.setScaleY(visible ? 1.0f : 0.1f); + if (notifyButton != null) { + notifyButton.setVisibility(notifyVisible && scheduledButton.getVisibility() != VISIBLE ? VISIBLE : GONE); + } } - if (notifyButton != null) { - notifyButton.setVisibility(notifyVisible && scheduledButton.getVisibility() != VISIBLE ? VISIBLE : GONE); - } - } else { + } else if (scheduledButton != null) { if (visible) { scheduledButton.setVisibility(VISIBLE); } @@ -6103,7 +6099,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe Bundle args1 = new Bundle(); if (lower_part > 0) { args1.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { args1.putInt("chat_id", -lower_part); } if (!accountInstance.getMessagesController().checkCanOpenChat(args1, fragment1)) { @@ -6378,8 +6374,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (trendingStickersAlert == this) { trendingStickersAlert = null; } + if (delegate != null) { + delegate.onTrendingStickersShowed(false); + } } }; + if (delegate != null) { + delegate.onTrendingStickersShowed(true); + } trendingStickersAlert.show(); } } @@ -6452,7 +6454,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } private boolean allowDragging() { - return stickersTabOpen && !(!stickersExpanded && messageEditText.length() > 0) && emojiView.areThereAnyStickers(); + return stickersTabOpen && !(!stickersExpanded && messageEditText.length() > 0) && emojiView.areThereAnyStickers() && !waitingForKeyboardOpen; } }); sizeNotifierLayout.addView(emojiView, sizeNotifierLayout.getChildCount() - 1); @@ -6850,6 +6852,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe showKeyboardOnResume = true; } else if (!AndroidUtilities.usingHardwareInput && !keyboardVisible && !AndroidUtilities.isInMultiwindow && (parentFragment == null || !parentFragment.isInBubbleMode())) { waitingForKeyboardOpen = true; + if (emojiView != null) { + emojiView.onTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0)); + } AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); } @@ -7448,6 +7453,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe this.adjustPanLayoutHelper = adjustPanLayoutHelper; } + public AdjustPanLayoutHelper getAdjustPanLayoutHelper() { + return adjustPanLayoutHelper; + } + public boolean pannelAniamationInProgress() { return panelAnimation != null; } @@ -7463,6 +7472,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe return animatedTop; } + public void checkAnimation() { + + } + private class ScrimDrawable extends Drawable { private Paint paint; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java index a7159358d..d72c41a25 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -318,6 +318,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N protected int avatarPicker; protected boolean avatarSearch; + protected boolean typeButtonsAvailable; private int selectedId; @@ -334,6 +335,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N private float baseSelectedTextViewTranslationY; private boolean menuShowed; protected SizeNotifierFrameLayout sizeNotifierFrameLayout; + private boolean openTransitionFinished; private Object viewChangeAnimator; @@ -609,7 +611,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N @Override protected boolean heightAnimationEnabled() { - if (isDismissed()) { + if (isDismissed() || !openTransitionFinished) { return false; } return !commentTextView.isPopupVisible(); @@ -1200,13 +1202,13 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N baseFragment.getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); return; } - openAudioLayout(); + openAudioLayout(true); } else if (num == 4) { if (Build.VERSION.SDK_INT >= 23 && baseFragment.getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { baseFragment.getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); return; } - openDocumentsLayout(); + openDocumentsLayout(true); } else if (num == 5) { if (Build.VERSION.SDK_INT >= 23) { if (baseFragment.getParentActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { @@ -1609,6 +1611,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N ChatActivity chatActivity = (ChatActivity) baseFragment; calcMandatoryInsets = chatActivity.isKeyboardVisible(); } + openTransitionFinished = false; } public void setEditingMessageObject(MessageObject messageObject) { @@ -1749,6 +1752,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 5 && grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { openContactsLayout(); + } else if (requestCode == 30 && locationLayout != null && currentAttachLayout == locationLayout && isShowing()) { + locationLayout.openShareLiveLocation(); } } @@ -1760,7 +1765,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N showLayout(contactsLayout); } - private void openAudioLayout() { + private void openAudioLayout(boolean show) { if (audioLayout == null) { layouts[3] = audioLayout = new ChatAttachAlertAudioLayout(this, getContext()); audioLayout.setDelegate((audios, caption, notify, scheduleDate) -> ((ChatActivity) baseFragment).sendAudio(audios, caption, notify, scheduleDate)); @@ -1770,10 +1775,12 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N TLRPC.Chat currentChat = chatActivity.getCurrentChat(); audioLayout.setMaxSelectedFiles(currentChat != null && !ChatObject.hasAdminRights(currentChat) && currentChat.slowmode_enabled || editingMessageObject != null ? 1 : -1); } - showLayout(audioLayout); + if (show) { + showLayout(audioLayout); + } } - private void openDocumentsLayout() { + private void openDocumentsLayout(boolean show) { if (documentLayout == null) { layouts[4] = documentLayout = new ChatAttachAlertDocumentLayout(this, getContext(), false); documentLayout.setDelegate(new ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate() { @@ -1806,7 +1813,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N @Override public void startMusicSelectActivity() { - openAudioLayout(); + openAudioLayout(true); } }); } @@ -1818,7 +1825,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N documentLayout.setMaxSelectedFiles(maxSelectedPhotos); documentLayout.setCanSelectOnlyImageFiles(true); } - showLayout(documentLayout); + if (show) { + showLayout(documentLayout); + } } private boolean showCommentTextView(boolean show, boolean animated) { @@ -1836,7 +1845,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (show) { frameLayout2.setVisibility(View.VISIBLE); writeButtonContainer.setVisibility(View.VISIBLE); - } else { + if (!typeButtonsAvailable) { + shadow.setVisibility(View.VISIBLE); + } + } else if (typeButtonsAvailable) { buttonsRecyclerView.setVisibility(View.VISIBLE); } if (animated) { @@ -1853,9 +1865,12 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N animators.add(ObjectAnimator.ofFloat(frameLayout2, View.TRANSLATION_Y, show ? 0.0f : AndroidUtilities.dp(48))); animators.add(ObjectAnimator.ofFloat(shadow, View.TRANSLATION_Y, show ? AndroidUtilities.dp(36) : AndroidUtilities.dp(48 + 36))); animators.add(ObjectAnimator.ofFloat(shadow, View.ALPHA, show ? 1.0f : 0.0f)); - } else { + } else if (typeButtonsAvailable) { animators.add(ObjectAnimator.ofFloat(buttonsRecyclerView, View.TRANSLATION_Y, show ? AndroidUtilities.dp(36) : 0)); animators.add(ObjectAnimator.ofFloat(shadow, View.TRANSLATION_Y, show ? AndroidUtilities.dp(36) : 0)); + } else { + shadow.setTranslationY(AndroidUtilities.dp(36)); + animators.add(ObjectAnimator.ofFloat(shadow, View.ALPHA, show ? 1.0f : 0.0f)); } commentsAnimator.playTogether(animators); @@ -1868,7 +1883,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (!show) { frameLayout2.setVisibility(View.INVISIBLE); writeButtonContainer.setVisibility(View.INVISIBLE); - } else { + if (!typeButtonsAvailable) { + shadow.setVisibility(View.INVISIBLE); + } + } else if (typeButtonsAvailable) { buttonsRecyclerView.setVisibility(View.INVISIBLE); } commentsAnimator = null; @@ -1895,13 +1913,19 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N frameLayout2.setTranslationY(show ? 0.0f : AndroidUtilities.dp(48)); shadow.setTranslationY(show ? AndroidUtilities.dp(36) : AndroidUtilities.dp(48 + 36)); shadow.setAlpha(show ? 1.0f : 0.0f); - } else { + } else if (typeButtonsAvailable) { buttonsRecyclerView.setTranslationY(show ? AndroidUtilities.dp(36) : 0); shadow.setTranslationY(show ? AndroidUtilities.dp(36) : 0); + } else { + shadow.setTranslationY(AndroidUtilities.dp(36)); + shadow.setAlpha(show ? 1.0f : 0.0f); } if (!show) { frameLayout2.setVisibility(View.INVISIBLE); writeButtonContainer.setVisibility(View.INVISIBLE); + if (!typeButtonsAvailable) { + shadow.setVisibility(View.INVISIBLE); + } } } return true; @@ -1980,9 +2004,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N setFocusable(true); editText.requestFocus(); if (showKeyboard) { - AndroidUtilities.runOnUIThread(() -> { - AndroidUtilities.showKeyboard(editText); - }); + AndroidUtilities.runOnUIThread(() -> AndroidUtilities.showKeyboard(editText)); } }, keyboardVisible ? 200 : 0); } @@ -2197,14 +2219,15 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N actionBarAnimation = null; } boolean needsSearchItem = avatarSearch || currentAttachLayout == photoLayout && !menuShowed && baseFragment instanceof ChatActivity && ((ChatActivity) baseFragment).allowSendGifs(); + boolean needMoreItem = avatarPicker != 0 || !menuShowed && currentAttachLayout == photoLayout && mediaEnabled; if (show) { if (needsSearchItem) { searchItem.setVisibility(View.VISIBLE); } - if (avatarPicker != 0 || !menuShowed && currentAttachLayout == photoLayout) { + if (needMoreItem) { selectedMenuItem.setVisibility(View.VISIBLE); } - } else if (avatarPicker == 0) { + } else if (typeButtonsAvailable) { buttonsRecyclerView.setVisibility(View.VISIBLE); } if (animated) { @@ -2216,7 +2239,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (needsSearchItem) { animators.add(ObjectAnimator.ofFloat(searchItem, View.ALPHA, show ? 1.0f : 0.0f)); } - if (avatarPicker != 0 || !menuShowed && currentAttachLayout == photoLayout) { + if (needMoreItem) { animators.add(ObjectAnimator.ofFloat(selectedMenuItem, View.ALPHA, show ? 1.0f : 0.0f)); } actionBarAnimation.playTogether(animators); @@ -2225,7 +2248,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public void onAnimationEnd(Animator animation) { if (actionBarAnimation != null) { if (show) { - if (avatarPicker == 0) { + if (typeButtonsAvailable) { buttonsRecyclerView.setVisibility(View.INVISIBLE); } } else { @@ -2245,7 +2268,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N actionBarAnimation.start(); } else { if (show) { - if (avatarPicker == 0) { + if (typeButtonsAvailable) { buttonsRecyclerView.setVisibility(View.INVISIBLE); } } @@ -2254,7 +2277,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (needsSearchItem) { searchItem.setAlpha(show ? 1.0f : 0.0f); } - if (avatarPicker != 0 || !menuShowed && currentAttachLayout == photoLayout) { + if (needMoreItem) { selectedMenuItem.setAlpha(show ? 1.0f : 0.0f); } if (!show) { @@ -2395,7 +2418,30 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N commentTextView.hidePopup(true); enterCommentEventSent = false; setFocusable(false); - if (currentAttachLayout != photoLayout) { + ChatAttachAlert.AttachAlertLayout layoutToSet; + if (editingMessageObject != null && editingMessageObject.hasValidGroupId() && (editingMessageObject.isMusic() || editingMessageObject.isDocument())) { + if (editingMessageObject.isMusic()) { + openAudioLayout(false); + layoutToSet = audioLayout; + selectedId = 3; + } else { + openDocumentsLayout(false); + layoutToSet = documentLayout; + selectedId = 4; + } + typeButtonsAvailable = false; + buttonsRecyclerView.setVisibility(View.GONE); + shadow.setVisibility(View.INVISIBLE); + } else { + layoutToSet = photoLayout; + typeButtonsAvailable = avatarPicker == 0; + selectedId = 1; + if (typeButtonsAvailable) { + buttonsRecyclerView.setVisibility(View.VISIBLE); + shadow.setVisibility(View.VISIBLE); + } + } + if (currentAttachLayout != layoutToSet) { if (actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(); } @@ -2403,18 +2449,17 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N currentAttachLayout.onHide(); currentAttachLayout.setVisibility(View.GONE); currentAttachLayout.onHidden(); - currentAttachLayout = photoLayout; + currentAttachLayout = layoutToSet; setAllowNestedScroll(true); if (currentAttachLayout.getParent() == null) { containerView.addView(currentAttachLayout, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } - selectedId = 1; - photoLayout.setAlpha(1.0f); - photoLayout.setVisibility(View.VISIBLE); - photoLayout.onShow(); - photoLayout.onShown(); - actionBar.setVisibility(View.VISIBLE); - actionBarShadow.setVisibility(View.VISIBLE); + layoutToSet.setAlpha(1.0f); + layoutToSet.setVisibility(View.VISIBLE); + layoutToSet.onShow(); + layoutToSet.onShown(); + actionBar.setVisibility(layoutToSet.needsActionBar() != 0 ? View.VISIBLE : View.INVISIBLE); + actionBarShadow.setVisibility(actionBar.getVisibility()); } updateCountButton(0); @@ -2449,6 +2494,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } currentAttachLayout.onOpenAnimationEnd(); AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton)); + openTransitionFinished = true; } @Override @@ -2471,6 +2517,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N avatarPicker = type; avatarSearch = search; if (avatarPicker != 0) { + typeButtonsAvailable = false; buttonsRecyclerView.setVisibility(View.GONE); shadow.setVisibility(View.GONE); if (avatarPicker == 2) { @@ -2478,6 +2525,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } else { selectedTextView.setText(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto)); } + } else { + typeButtonsAvailable = true; } } @@ -2593,9 +2642,17 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N galleryButton = buttonsCount++; documentButton = buttonsCount++; } else if (editingMessageObject != null) { - galleryButton = buttonsCount++; - documentButton = buttonsCount++; - musicButton = buttonsCount++; + if ((editingMessageObject.isMusic() || editingMessageObject.isDocument()) && editingMessageObject.hasValidGroupId()) { + if (editingMessageObject.isMusic()) { + musicButton = buttonsCount++; + } else { + documentButton = buttonsCount++; + } + } else { + galleryButton = buttonsCount++; + documentButton = buttonsCount++; + musicButton = buttonsCount++; + } } else { if (mediaEnabled) { galleryButton = buttonsCount++; @@ -2714,4 +2771,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public void setAllowNestedScroll(boolean allowNestedScroll) { this.allowNestedScroll = allowNestedScroll; } + + public BaseFragment getBaseFragment() { + return baseFragment; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertAudioLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertAudioLayout.java index 56df56382..541a7878c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertAudioLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertAudioLayout.java @@ -81,6 +81,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou private boolean ignoreLayout; private ArrayList audioEntries = new ArrayList<>(); + private ArrayList selectedAudiosOrder = new ArrayList<>(); private LongSparseArray selectedAudios = new LongSparseArray<>(); private AudioSelectDelegate delegate; @@ -371,6 +372,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou @Override void onHidden() { selectedAudios.clear(); + selectedAudiosOrder.clear(); } @Override @@ -463,6 +465,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou boolean add; if (selectedAudios.indexOfKey(audioEntry.id) >= 0) { selectedAudios.remove(audioEntry.id); + selectedAudiosOrder.remove(audioEntry); audioCell.setChecked(false, true); add = false; } else { @@ -471,6 +474,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou return; } selectedAudios.put(audioEntry.id, audioEntry); + selectedAudiosOrder.add(audioEntry); audioCell.setChecked(true, true); add = true; } @@ -489,8 +493,8 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou } sendPressed = true; ArrayList audios = new ArrayList<>(); - for (int a = 0; a < selectedAudios.size(); a++) { - audios.add(selectedAudios.valueAt(a).messageObject); + for (int a = 0; a < selectedAudiosOrder.size(); a++) { + audios.add(selectedAudiosOrder.get(a).messageObject); } delegate.didSelectAudio(audios, parentAlert.commentTextView.getText().toString(), notify, scheduleDate); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java index ea4ce61a8..7e3ae8c7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java @@ -101,6 +101,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private ArrayList history = new ArrayList<>(); private DocumentSelectActivityDelegate delegate; private HashMap selectedFiles = new HashMap<>(); + private ArrayList selectedFilesOrder = new ArrayList<>(); private boolean scrolling; private ArrayList recentItems = new ArrayList<>(); private int maxSelectedFiles = -1; @@ -511,7 +512,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa return; } sendPressed = true; - ArrayList files = new ArrayList<>(selectedFiles.keySet()); + ArrayList files = new ArrayList<>(selectedFilesOrder); delegate.didSelectFiles(files, parentAlert.commentTextView.getText().toString(), notify, scheduleDate); parentAlert.dismiss(); } @@ -524,6 +525,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa boolean add; if (selectedFiles.containsKey(path)) { selectedFiles.remove(path); + selectedFilesOrder.remove(path); add = false; } else { if (!item.file.canRead()) { @@ -546,6 +548,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa return false; } selectedFiles.put(path, item); + selectedFilesOrder.add(path); add = true; } scrolling = false; @@ -686,6 +689,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa @Override void onShow() { selectedFiles.clear(); + selectedFilesOrder.clear(); history.clear(); listRoots(); updateSearchButton(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java index 30fb0dab3..9e861addb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java @@ -17,6 +17,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -148,6 +149,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa private FrameLayout lastPressedMarkerView; private boolean checkPermission = true; + private boolean checkBackgroundPermission = true; private boolean searching; private boolean searchWas; @@ -1118,10 +1120,23 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa animatorSet.start(); } - private void openShareLiveLocation() { + public void openShareLiveLocation() { if (delegate == null || getParentActivity() == null || myLocation == null) { return; } + if (checkBackgroundPermission && Build.VERSION.SDK_INT >= 29) { + Activity activity = getParentActivity(); + if (activity != null) { + checkBackgroundPermission = false; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + int lastTime = preferences.getInt("backgroundloc", 0); + if (Math.abs(System.currentTimeMillis() / 1000 - lastTime) > 24 * 60 * 60 && activity.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { + preferences.edit().putInt("backgroundloc", (int) (System.currentTimeMillis() / 1000)).commit(); + AlertsCreator.createBackgroundLocationPermissionDialog(activity, getMessagesController().getUser(getUserConfig().getClientUserId()), this::openShareLiveLocation).show(); + return; + } + } + } TLRPC.User user = null; if ((int) dialogId > 0) { user = parentAlert.baseFragment.getMessagesController().getUser((int) dialogId); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java index bf43307bb..c1cc3a92a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -2062,8 +2062,11 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } float topLocal = child.getY() + gridView.getY() + getY(); - float top = topLocal + parentAlert.getSheetContainer().getY(); + float top = topLocal + parentAlert.getSheetContainer().getY(); float left = child.getX() + gridView.getX() + getX() + parentAlert.getSheetContainer().getX(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + left -= getRootWindowInsets().getSystemWindowInsetLeft(); + } float maxY = (Build.VERSION.SDK_INT >= 21 && !parentAlert.inBubbleMode ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); if (topLocal < maxY) { 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 0b9dd9f53..e40d3b056 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -74,13 +74,13 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent avatarImageView = new BackupImageView(context); if (parentFragment != null) { sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(chatActivity); - if (parentFragment.isThreadChat()) { + if (parentFragment.isThreadChat() || parentFragment.getChatMode() == 2) { avatarImageView.setVisibility(GONE); } } avatarImageView.setRoundRadius(AndroidUtilities.dp(21)); addView(avatarImageView); - if (parentFragment != null && !parentFragment.isInScheduleMode() && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { + if (parentFragment != null && parentFragment.getChatMode() == 0 && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { avatarImageView.setOnClickListener(v -> openProfile(true)); } @@ -109,17 +109,17 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent timeItem.setContentDescription(LocaleController.getString("SetTimer", R.string.SetTimer)); } - if (parentFragment != null && !parentFragment.isInScheduleMode()) { + if (parentFragment != null && parentFragment.getChatMode() == 0) { if (!parentFragment.isThreadChat() && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { setOnClickListener(v -> openProfile(false)); } TLRPC.Chat chat = parentFragment.getCurrentChat(); - statusDrawables[0] = new TypingDotsDrawable(); - statusDrawables[1] = new RecordStatusDrawable(); - statusDrawables[2] = new SendingFileDrawable(); - statusDrawables[3] = new PlayingGameDrawable(); - statusDrawables[4] = new RoundStatusDrawable(); + statusDrawables[0] = new TypingDotsDrawable(false); + statusDrawables[1] = new RecordStatusDrawable(false); + statusDrawables[2] = new SendingFileDrawable(false); + statusDrawables[3] = new PlayingGameDrawable(false); + statusDrawables[4] = new RoundStatusDrawable(false); for (int a = 0; a < statusDrawables.length; a++) { statusDrawables[a].setIsChat(chat != null); } @@ -309,14 +309,14 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent return; } TLRPC.User user = parentFragment.getCurrentUser(); - if (UserObject.isUserSelf(user) || UserObject.isReplyUser(user) || parentFragment.isInScheduleMode()) { + if (UserObject.isUserSelf(user) || UserObject.isReplyUser(user) || parentFragment.getChatMode() != 0) { if (subtitleTextView.getVisibility() != GONE) { subtitleTextView.setVisibility(GONE); } return; } TLRPC.Chat chat = parentFragment.getCurrentChat(); - CharSequence printString = MessagesController.getInstance(currentAccount).getPrintingString(parentFragment.getDialogId(), parentFragment.getThreadId()); + CharSequence printString = MessagesController.getInstance(currentAccount).getPrintingString(parentFragment.getDialogId(), parentFragment.getThreadId(), false); if (printString != null) { printString = TextUtils.replace(printString, new String[]{"..."}, new String[]{""}); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java index 142f5220f..5cfc7d680 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java @@ -51,7 +51,7 @@ public class CheckBox2 extends View { } public void setDrawBackgroundAsArc(int type) { - checkBoxBase.setDrawBackgroundAsArc(type); + checkBoxBase.setBackgroundType(type); } public float getProgress() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java index cad339b3a..debc97ddb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java @@ -6,6 +6,8 @@ import android.animation.ObjectAnimator; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; @@ -55,7 +57,7 @@ public class CheckBoxBase { private boolean useDefaultCheck; private boolean drawUnchecked = true; - private int drawBackgroundAsArc; + private int backgroundType; private float size; @@ -63,6 +65,8 @@ public class CheckBoxBase { private ProgressDelegate progressDelegate; + private Theme.MessageDrawable messageDrawable; + public interface ProgressDelegate { void setProgress(float progress); } @@ -151,9 +155,11 @@ public class CheckBoxBase { enabled = value; } - public void setDrawBackgroundAsArc(int type) { - drawBackgroundAsArc = type; - if (type == 4 || type == 5) { + public void setBackgroundType(int type) { + backgroundType = type; + if (type == 12 || type == 13) { + backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1)); + } else if (type == 4 || type == 5) { backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1.9f)); if (type == 5) { checkPaint.setStrokeWidth(AndroidUtilities.dp(1.5f)); @@ -196,6 +202,10 @@ public class CheckBoxBase { checkColorKey = check; } + public void setBackgroundDrawable(Theme.MessageDrawable drawable) { + messageDrawable = drawable; + } + public void setUseDefaultCheck(boolean value) { useDefaultCheck = value; } @@ -243,8 +253,12 @@ public class CheckBoxBase { drawBitmap.eraseColor(0); float rad = AndroidUtilities.dp(size / 2); float outerRad = rad; - if (drawBackgroundAsArc != 0 && drawBackgroundAsArc != 11) { - outerRad -= AndroidUtilities.dp(0.2f); + if (backgroundType == 12 || backgroundType == 13) { + rad = outerRad = AndroidUtilities.dp(10); + } else { + if (backgroundType != 0 && backgroundType != 11) { + outerRad -= AndroidUtilities.dp(0.2f); + } } float roundProgress = progress >= 0.5f ? 1.0f : progress / 0.5f; @@ -254,10 +268,14 @@ public class CheckBoxBase { if (backgroundColorKey != null) { if (drawUnchecked) { - if (drawBackgroundAsArc == 6 || drawBackgroundAsArc == 7) { + if (backgroundType == 12 || backgroundType == 13) { + paint.setColor(Theme.getColor(backgroundColorKey)); + paint.setAlpha((int) (255 * backgroundAlpha)); + backgroundPaint.setColor(Theme.getColor(checkColorKey)); + } else if (backgroundType == 6 || backgroundType == 7) { paint.setColor(Theme.getColor(background2ColorKey)); backgroundPaint.setColor(Theme.getColor(checkColorKey)); - } else if (drawBackgroundAsArc == 10) { + } else if (backgroundType == 10) { backgroundPaint.setColor(Theme.getColor(background2ColorKey)); } else { paint.setColor((Theme.getServiceMessageColor() & 0x00ffffff) | 0x28000000); @@ -269,7 +287,7 @@ public class CheckBoxBase { } else { if (drawUnchecked) { paint.setColor(Color.argb((int) (25 * backgroundAlpha), 0, 0, 0)); - if (drawBackgroundAsArc == 8) { + if (backgroundType == 8) { backgroundPaint.setColor(Theme.getColor(background2ColorKey)); } else { backgroundPaint.setColor(AndroidUtilities.getOffsetColor(0xffffffff, Theme.getColor(checkColorKey), progress, backgroundAlpha)); @@ -280,9 +298,11 @@ public class CheckBoxBase { } if (drawUnchecked) { - if (drawBackgroundAsArc == 8 || drawBackgroundAsArc == 10) { + if (backgroundType == 12 || backgroundType == 13) { + //draw nothing + } else if (backgroundType == 8 || backgroundType == 10) { canvas.drawCircle(cx, cy, rad - AndroidUtilities.dp(1.5f), backgroundPaint); - } else if (drawBackgroundAsArc == 6 || drawBackgroundAsArc == 7) { + } else if (backgroundType == 6 || backgroundType == 7) { canvas.drawCircle(cx, cy, rad - AndroidUtilities.dp(1), paint); canvas.drawCircle(cx, cy, rad - AndroidUtilities.dp(1.5f), backgroundPaint); } else { @@ -290,17 +310,30 @@ public class CheckBoxBase { } } paint.setColor(Theme.getColor(checkColorKey)); - if (drawBackgroundAsArc != 7 && drawBackgroundAsArc != 8 && drawBackgroundAsArc != 9 && drawBackgroundAsArc != 10) { - if (drawBackgroundAsArc == 0 || drawBackgroundAsArc == 11) { + if (backgroundType != 7 && backgroundType != 8 && backgroundType != 9 && backgroundType != 10) { + if (backgroundType == 12 || backgroundType == 13) { + backgroundPaint.setStyle(Paint.Style.FILL); + if (messageDrawable != null && messageDrawable.hasGradient()) { + LinearGradient shader = messageDrawable.getGradientShader(); + Matrix matrix = messageDrawable.getMatrix(); + matrix.setTranslate(0, -messageDrawable.getTopY() + bounds.top); + shader.setLocalMatrix(matrix); + backgroundPaint.setShader(shader); + } else { + backgroundPaint.setShader(null); + } + canvas.drawCircle(cx, cy, (rad - AndroidUtilities.dp(1)) * backgroundAlpha, backgroundPaint); + backgroundPaint.setStyle(Paint.Style.STROKE); + } else if (backgroundType == 0 || backgroundType == 11) { canvas.drawCircle(cx, cy, rad, backgroundPaint); } else { rect.set(cx - outerRad, cy - outerRad, cx + outerRad, cy + outerRad); int startAngle; int sweepAngle; - if (drawBackgroundAsArc == 6) { + if (backgroundType == 6) { startAngle = 0; sweepAngle = (int) (-360 * progress); - } else if (drawBackgroundAsArc == 1) { + } else if (backgroundType == 1) { startAngle = -90; sweepAngle = (int) (-270 * progress); } else { @@ -308,7 +341,7 @@ public class CheckBoxBase { sweepAngle = (int) (270 * progress); } - if (drawBackgroundAsArc == 6) { + if (backgroundType == 6) { int color = Theme.getColor(Theme.key_dialogBackground); int alpha = Color.alpha(color); backgroundPaint.setColor(color); @@ -318,19 +351,17 @@ public class CheckBoxBase { alpha = Color.alpha(color); backgroundPaint.setColor(color); backgroundPaint.setAlpha((int) (alpha * progress)); - canvas.drawArc(rect, startAngle, sweepAngle, false, backgroundPaint); - } else { - canvas.drawArc(rect, startAngle, sweepAngle, false, backgroundPaint); } + canvas.drawArc(rect, startAngle, sweepAngle, false, backgroundPaint); } } if (roundProgress > 0) { float checkProgress = progress < 0.5f ? 0.0f : (progress - 0.5f) / 0.5f; - if (drawBackgroundAsArc == 9) { + if (backgroundType == 9) { paint.setColor(Theme.getColor(background2ColorKey)); - } else if (drawBackgroundAsArc == 11 || drawBackgroundAsArc == 6 || drawBackgroundAsArc == 7 || drawBackgroundAsArc == 10 || !drawUnchecked && backgroundColorKey != null) { + } else if (backgroundType == 11 || backgroundType == 6 || backgroundType == 7 || backgroundType == 10 || !drawUnchecked && backgroundColorKey != null) { paint.setColor(Theme.getColor(backgroundColorKey)); } else { paint.setColor(Theme.getColor(enabled ? Theme.key_checkbox : Theme.key_checkboxDisabled)); @@ -341,9 +372,14 @@ public class CheckBoxBase { checkPaint.setColor(Theme.getColor(Theme.key_checkboxCheck)); } - rad -= AndroidUtilities.dp(0.5f); - bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getHeight() / 2, rad, paint); - bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getWidth() / 2, rad * (1.0f - roundProgress), eraser); + if (backgroundType == 12 || backgroundType == 13) { + paint.setAlpha((int) (255 * roundProgress)); + bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getHeight() / 2, rad * roundProgress, paint); + } else { + rad -= AndroidUtilities.dp(0.5f); + bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getHeight() / 2, rad, paint); + bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getHeight() / 2, rad * (1.0f - roundProgress), eraser); + } canvas.drawBitmap(drawBitmap, cx - drawBitmap.getWidth() / 2, cy - drawBitmap.getHeight() / 2, null); if (checkProgress != 0) { @@ -377,7 +413,7 @@ public class CheckBoxBase { } else { path.reset(); - float scale = drawBackgroundAsArc == 5 ? 0.8f : 1.0f; + float scale = backgroundType == 5 ? 0.8f : 1.0f; float checkSide = AndroidUtilities.dp(9 * scale) * checkProgress; float smallCheckSide = AndroidUtilities.dp(4 * scale) * checkProgress; int x = cx - AndroidUtilities.dp(1.5f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java index a99592ab7..3c283d5b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EllipsizeSpanAnimator.java @@ -9,8 +9,6 @@ import android.text.TextPaint; import android.text.style.CharacterStyle; import android.view.View; -import com.google.android.exoplayer2.util.Log; - import java.util.ArrayList; public class EllipsizeSpanAnimator { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastGridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastGridLayoutManager.java index dd5704639..66c7a9aa1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastGridLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastGridLayoutManager.java @@ -47,15 +47,18 @@ public class FillLastGridLayoutManager extends GridLayoutManager { int count = adapter.getItemCount() - 1; int allHeight = 0; final SpanSizeLookup spanSizeLookup = getSpanSizeLookup(); + boolean add = true; for (int a = 0; a < count; a++) { final int spanSize = spanSizeLookup.getSpanSize(a); spanCounter += spanSize; - if (spanSize == spanCount || spanCounter > spanCount) { - spanCounter = 0; - } else if (spanCounter != 1) { + spanCounter = spanSize; + add = true; + } + if (!add) { continue; } + add = false; int type = adapter.getItemViewType(a); RecyclerView.ViewHolder holder = heights.get(type, null); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java new file mode 100644 index 000000000..4586ea899 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -0,0 +1,262 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.os.SystemClock; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.Theme; + +public class FlickerLoadingView extends View { + + public final static int DIALOG_TYPE = 1; + public final static int PHOTOS_TYPE = 2; + public final static int FILES_TYPE = 3; + public final static int AUDIO_TYPE = 4; + public final static int LINKS_TYPE = 5; + + int gradientWidth; + LinearGradient gradient; + Paint paint = new Paint(); + private long lastUpdateTime; + private int totalTranslation; + private Matrix matrix; + RectF rectF = new RectF(); + int color0; + int color1; + private boolean showDate = true; + + private boolean isSingleCell; + + int viewType; + + public void setViewType(int type) { + this.viewType = type; + invalidate(); + } + + public void setIsSingleCell(boolean b) { + isSingleCell = b; + } + + public int getViewType() { + return viewType; + } + + public int getColumnsCount() { + return 2; + } + + public FlickerLoadingView(Context context) { + super(context); + matrix = new Matrix(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (isSingleCell) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getCellHeight(), MeasureSpec.EXACTLY)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + @Override + protected void onDraw(Canvas canvas) { + int color0 = Theme.getColor(Theme.key_dialogBackground); + int color1 = Theme.getColor(Theme.key_windowBackgroundGray); + if (this.color1 != color1 || this.color0 != color0) { + this.color0 = color0; + this.color1 = color1; + if (isSingleCell) { + gradient = new LinearGradient(0, 0, gradientWidth = AndroidUtilities.dp(200), 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + } else { + gradient = new LinearGradient(0, 0, 0, gradientWidth = AndroidUtilities.dp(600), new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + } + paint.setShader(gradient); + } + if (getViewType() == DIALOG_TYPE) { + int h = 0; + while (h < getMeasuredHeight()) { + int r = AndroidUtilities.dp(25); + canvas.drawCircle(checkRtl(AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(78) >> 1), r, paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(20), AndroidUtilities.dp(140), h + AndroidUtilities.dp(28)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(42), AndroidUtilities.dp(260), h + AndroidUtilities.dp(50)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + if (showDate) { + rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(20), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(28)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + } + + h += getCellHeight(); + if (isSingleCell) { + break; + } + } + } else if (getViewType() == PHOTOS_TYPE) { + int photoWidth = (getMeasuredWidth() - (AndroidUtilities.dp(2) * (getColumnsCount() - 1))) / getColumnsCount(); + int h = 0; + while (h < getMeasuredHeight()) { + for (int i = 0; i < getColumnsCount(); i++) { + int x = i * (photoWidth + AndroidUtilities.dp(2)); + canvas.drawRect(x, h, x + photoWidth, h + photoWidth, paint); + } + h += photoWidth + AndroidUtilities.dp(2); + if (isSingleCell) { + break; + } + } + } else if (getViewType() == 3) { + int h = 0; + while (h < getMeasuredHeight()) { + rectF.set(AndroidUtilities.dp(12), h + AndroidUtilities.dp(8), AndroidUtilities.dp(52), h + AndroidUtilities.dp(48)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(260), h + AndroidUtilities.dp(42)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + if (showDate) { + rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + } + + h += getCellHeight(); + if (isSingleCell) { + break; + } + } + } else if (getViewType() == 4) { + int h = 0; + while (h < getMeasuredHeight()) { + int radius = AndroidUtilities.dp(44) >> 1; + canvas.drawCircle(checkRtl(AndroidUtilities.dp(12) + radius), h + AndroidUtilities.dp(6) + radius, radius, paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(260), h + AndroidUtilities.dp(42)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + if (showDate) { + rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + } + + h += getCellHeight(); + if (isSingleCell) { + break; + } + } + } else if (getViewType() == 5) { + int h = 0; + while (h < getMeasuredHeight()) { + rectF.set(AndroidUtilities.dp(10), h + AndroidUtilities.dp(11), AndroidUtilities.dp(62), h + AndroidUtilities.dp(11 + 52)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(268), h + AndroidUtilities.dp(42)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34 + 20), AndroidUtilities.dp(120 + 68), h + AndroidUtilities.dp(42 + 20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + if (showDate) { + rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + } + + h += getCellHeight(); + if (isSingleCell) { + break; + } + } + } + + long newUpdateTime = SystemClock.elapsedRealtime(); + long dt = Math.abs(lastUpdateTime - newUpdateTime); + if (dt > 17) { + dt = 16; + } + lastUpdateTime = newUpdateTime; + if (isSingleCell) { + totalTranslation += dt * getMeasuredWidth() / 400.0f; + if (totalTranslation >= getMeasuredWidth() * 2) { + totalTranslation = -gradientWidth * 2; + } + matrix.setTranslate(totalTranslation, 0); + } else { + totalTranslation += dt * getMeasuredHeight() / 400.0f; + if (totalTranslation >= getMeasuredHeight() * 2) { + totalTranslation = -gradientWidth * 2; + } + matrix.setTranslate(0, totalTranslation); + } + gradient.setLocalMatrix(matrix); + invalidate(); + } + + private float checkRtl(float x) { + if (LocaleController.isRTL) { + return getMeasuredWidth() - x; + } + return x; + } + + private void checkRtl(RectF rectF) { + if (LocaleController.isRTL) { + rectF.left = getMeasuredWidth() - rectF.left; + rectF.right = getMeasuredWidth() - rectF.right; + } + } + + private int getCellHeight() { + if (getViewType() == DIALOG_TYPE) { + return AndroidUtilities.dp(78) + 1; + } else if (getViewType() == PHOTOS_TYPE) { + int photoWidth = (getMeasuredWidth() - (AndroidUtilities.dp(2) * (getColumnsCount() - 1))) / getColumnsCount(); + return photoWidth + AndroidUtilities.dp(2); + } else if (getViewType() == 3) { + return AndroidUtilities.dp(56) + 1; + } else if (getViewType() == 4) { + return AndroidUtilities.dp(56) + 1; + } else if (getViewType() == 5) { + return AndroidUtilities.dp(80); + } + return 0; + } + + public void showDate(boolean showDate) { + this.showDate = showDate; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index d6ab133bd..adccb9888 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -59,6 +59,7 @@ import java.util.ArrayList; public class FragmentContextView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private ImageView playButton; + private PlayPauseDrawable playPauseDrawable; private TextView titleTextView; private AnimatorSet animatorSet; private BaseFragment fragment; @@ -122,12 +123,13 @@ public class FragmentContextView extends FrameLayout implements NotificationCent frameLayout.addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); View shadow = new View(context); - shadow.setBackgroundResource(R.drawable.header_shadow); - addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.TOP, 0, 36, 0, 0)); + shadow.setBackgroundResource(R.drawable.blockpanel_shadow); + addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.LEFT | Gravity.TOP, 0, 36, 0, 0)); playButton = new ImageView(context); playButton.setScaleType(ImageView.ScaleType.CENTER); playButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_inappPlayerPlayPause), PorterDuff.Mode.MULTIPLY)); + playButton.setImageDrawable(playPauseDrawable = new PlayPauseDrawable(14)); if (Build.VERSION.SDK_INT >= 21) { playButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_inappPlayerPlayPause) & 0x19ffffff, 1, AndroidUtilities.dp(14))); } @@ -178,7 +180,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent closeButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14))); } closeButton.setScaleType(ImageView.ScaleType.CENTER); - addView(closeButton, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); + addView(closeButton, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); closeButton.setOnClickListener(v -> { if (currentStyle == 2) { AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity()); @@ -239,7 +241,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent if (lower_part != 0) { if (lower_part > 0) { args.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { args.putInt("chat_id", -lower_part); } } else { @@ -269,8 +271,6 @@ public class FragmentContextView extends FrameLayout implements NotificationCent break; } } - } else { - did = 0; } if (did != 0) { openSharingLocation(LocationController.getInstance(account).getSharingLocationInfo(did)); @@ -390,7 +390,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent playbackSpeedButton.setVisibility(VISIBLE); } closeButton.setContentDescription(LocaleController.getString("AccDescrClosePlayer", R.string.AccDescrClosePlayer)); - } else if (style == 2) { + } else { playButton.setLayoutParams(LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT, 8, 0, 0, 0)); titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35 + 16, 0, 36, 0)); closeButton.setContentDescription(LocaleController.getString("AccDescrStopLiveLocation", R.string.AccDescrStopLiveLocation)); @@ -466,7 +466,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, AndroidUtilities.dp2(39)); + super.onMeasure(widthMeasureSpec, AndroidUtilities.dp2(38)); } @Override @@ -565,6 +565,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent if (fragment instanceof DialogsActivity) { String liveLocation = LocaleController.getString("LiveLocationContext", R.string.LiveLocationContext); String param; + String str; ArrayList infos = new ArrayList<>(); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { infos.addAll(LocationController.getInstance(a).sharingLocationsUI); @@ -575,6 +576,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent if (lower_id > 0) { TLRPC.User user = MessagesController.getInstance(info.messageObject.currentAccount).getUser(lower_id); param = UserObject.getFirstName(user); + str = LocaleController.getString("AttachLiveLocationIsSharing", R.string.AttachLiveLocationIsSharing); } else { TLRPC.Chat chat = MessagesController.getInstance(info.messageObject.currentAccount).getChat(-lower_id); if (chat != null) { @@ -582,11 +584,13 @@ public class FragmentContextView extends FrameLayout implements NotificationCent } else { param = ""; } + str = LocaleController.getString("AttachLiveLocationIsSharingChat", R.string.AttachLiveLocationIsSharingChat); } } else { param = LocaleController.formatPluralString("Chats", infos.size()); + str = LocaleController.getString("AttachLiveLocationIsSharingChats", R.string.AttachLiveLocationIsSharingChats); } - String fullString = String.format(LocaleController.getString("AttachLiveLocationIsSharing", R.string.AttachLiveLocationIsSharing), liveLocation, param); + String fullString = String.format(str, liveLocation, param); int start = fullString.indexOf(liveLocation); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(fullString); titleTextView.setEllipsize(TextUtils.TruncateAt.END); @@ -777,10 +781,10 @@ public class FragmentContextView extends FrameLayout implements NotificationCent setVisibility(VISIBLE); } if (MediaController.getInstance().isMessagePaused()) { - playButton.setImageResource(R.drawable.miniplayer_play); + playPauseDrawable.setPause(false, !create); playButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } else { - playButton.setImageResource(R.drawable.miniplayer_pause); + playPauseDrawable.setPause(true, !create); playButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } if (lastMessageObject != messageObject || prevStyle != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java index 7f044f017..1a906ec3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java @@ -42,6 +42,8 @@ public class HintView extends FrameLayout { private boolean isTopArrow; private String overrideText; private int shownY; + private float translationY; + private float extraTranslationY; private int bottomOffset; private long showingDuration = 2000; @@ -105,6 +107,15 @@ public class HintView extends FrameLayout { } } + public void setExtraTranslationY(float value) { + extraTranslationY = value; + setTranslationY(extraTranslationY + translationY); + } + + public float getBaseTranslationY() { + return translationY; + } + public boolean showForMessageCell(ChatMessageCell cell, boolean animated) { return showForMessageCell(cell, null, 0, 0, animated); } @@ -185,9 +196,9 @@ public class HintView extends FrameLayout { int parentWidth = parentView.getMeasuredWidth(); if (isTopArrow) { - setTranslationY(AndroidUtilities.dp(44)); + setTranslationY(extraTranslationY + (translationY = AndroidUtilities.dp(44))); } else { - setTranslationY(top - getMeasuredHeight()); + setTranslationY(extraTranslationY + (translationY = top - getMeasuredHeight())); } int iconX = cell.getLeft() + centerX; int left = AndroidUtilities.dp(19); @@ -268,6 +279,8 @@ public class HintView extends FrameLayout { if (currentType == 4) { top += AndroidUtilities.dp(4); + } else if (currentType == 6) { + top += view.getMeasuredHeight() + getMeasuredHeight() + AndroidUtilities.dp(10); } int centerX; @@ -289,10 +302,10 @@ public class HintView extends FrameLayout { top -= bottomOffset; int parentWidth = parentView.getMeasuredWidth(); - if (isTopArrow) { - setTranslationY(AndroidUtilities.dp(44)); + if (isTopArrow && currentType != 6) { + setTranslationY(extraTranslationY + (translationY = AndroidUtilities.dp(44))); } else { - setTranslationY(top - getMeasuredHeight()); + setTranslationY(extraTranslationY + (translationY = top - getMeasuredHeight())); } final int offset; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java index 44f04a594..082495e0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java @@ -268,7 +268,7 @@ public class MediaActionDrawable extends Drawable { if (messageDrawable != null && messageDrawable.hasGradient() && !hasOverlayImage) { LinearGradient shader = messageDrawable.getGradientShader(); Matrix matrix = messageDrawable.getMatrix(); - matrix.postTranslate(0, bounds.top); + matrix.setTranslate(0, -messageDrawable.getTopY() + bounds.top); shader.setLocalMatrix(matrix); paint.setShader(shader); paint2.setShader(shader); @@ -715,13 +715,18 @@ public class MediaActionDrawable extends Drawable { progress1 = 1.0f; progress2 = 0.0f; } + paint.setAlpha(255); } else { progress1 = 0.0f; progress2 = 1.0f; + if (nextIcon != ICON_CHECK) { + paint.setAlpha((int) (255 * (1.0f - transitionProgress))); + } else { + paint.setAlpha(255); + } } int y = cy + AndroidUtilities.dp(7); int x = cx - AndroidUtilities.dp(3); - paint.setAlpha(255); if (progress1 < 1) { canvas.drawLine(x - AndroidUtilities.dp(6), y - AndroidUtilities.dp(6), x - AndroidUtilities.dp(6) * progress1, y - AndroidUtilities.dp(6) * progress1, paint); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MsgClockDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MsgClockDrawable.java new file mode 100644 index 000000000..8c500f66e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MsgClockDrawable.java @@ -0,0 +1,85 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; + +import androidx.annotation.Nullable; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; + +public class MsgClockDrawable extends Drawable { + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + int alpha = 255; + int colorAlpha = 255; + + long startTime; + + public MsgClockDrawable() { + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeWidth(AndroidUtilities.dp(1f)); + startTime = System.currentTimeMillis(); + } + + @Override + public void draw(Canvas canvas) { + Rect bounds = getBounds(); + int r = Math.min(bounds.width(), bounds.height()); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), (r >> 1) - AndroidUtilities.dp(0.5f), paint); + + long currentTime = System.currentTimeMillis(); + float rotateTime = 1500; + float rotateHourTime = rotateTime * 3; + + canvas.save(); + canvas.rotate(360 * ((currentTime - startTime) % rotateTime) / rotateTime, bounds.centerX(), bounds.centerY()); + canvas.drawLine(bounds.centerX(), bounds.centerY(), bounds.centerX(), bounds.centerY() - AndroidUtilities.dp(3), paint); + canvas.restore(); + + canvas.save(); + canvas.rotate(360 * ((currentTime - startTime) % rotateHourTime) / rotateHourTime, bounds.centerX(), bounds.centerY()); + canvas.drawLine(bounds.centerX(), bounds.centerY(), bounds.centerX() + AndroidUtilities.dp(2.3f), bounds.centerY(), paint); + canvas.restore(); + } + + public void setColor(int color) { + colorAlpha = Color.alpha(color); + paint.setColor(color); + } + + @Override + public int getIntrinsicHeight() { + return AndroidUtilities.dp(12); + } + + @Override + public int getIntrinsicWidth() { + return AndroidUtilities.dp(12); + } + + @Override + public void setAlpha(int i) { + if (alpha != i) { + alpha = i; + paint.setAlpha((int) (alpha * (colorAlpha / 255f))); + } + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java index 99b0f548a..39e47a777 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java @@ -35,6 +35,7 @@ public class NumberTextView extends View { private ObjectAnimator animator; private float progress = 0.0f; private int currentNumber = 1; + private boolean addNumber; public NumberTextView(Context context) { super(context); @@ -54,6 +55,10 @@ public class NumberTextView extends View { return progress; } + public void setAddNumber() { + addNumber = true; + } + public void setNumber(int number, boolean animated) { if (currentNumber == number && animated) { return; @@ -65,9 +70,18 @@ public class NumberTextView extends View { oldLetters.clear(); oldLetters.addAll(letters); letters.clear(); - String oldText = String.format(Locale.US, "%d", currentNumber); - String text = String.format(Locale.US, "%d", number); - boolean forwardAnimation = number > currentNumber; + String oldText; + String text; + boolean forwardAnimation; + if (addNumber) { + oldText = String.format(Locale.US, "#%d", currentNumber); + text = String.format(Locale.US, "#%d", number); + forwardAnimation = number < currentNumber; + } else { + oldText = String.format(Locale.US, "%d", currentNumber); + text = String.format(Locale.US, "%d", number); + forwardAnimation = number > currentNumber; + } currentNumber = number; progress = 0; for (int a = 0; a < text.length(); a++) { @@ -83,7 +97,7 @@ public class NumberTextView extends View { } if (animated && !oldLetters.isEmpty()) { animator = ObjectAnimator.ofFloat(this, "progress", forwardAnimation ? -1 : 1, 0); - animator.setDuration(150); + animator.setDuration(addNumber ? 180 : 150); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -121,6 +135,7 @@ public class NumberTextView extends View { return; } float height = letters.get(0).getHeight(); + float translationHeight = addNumber ? AndroidUtilities.dp(4) : height; canvas.save(); canvas.translate(getPaddingLeft(), (getMeasuredHeight() - height) / 2); int count = Math.max(letters.size(), oldLetters.size()); @@ -132,12 +147,12 @@ public class NumberTextView extends View { if (old != null) { textPaint.setAlpha((int) (255 * progress)); canvas.save(); - canvas.translate(0, (progress - 1.0f) * height); + canvas.translate(0, (progress - 1.0f) * translationHeight); old.draw(canvas); canvas.restore(); if (layout != null) { textPaint.setAlpha((int) (255 * (1.0f - progress))); - canvas.translate(0, progress * height); + canvas.translate(0, progress * translationHeight); } } else { textPaint.setAlpha(255); @@ -146,14 +161,14 @@ public class NumberTextView extends View { if (old != null) { textPaint.setAlpha((int) (255 * -progress)); canvas.save(); - canvas.translate(0, (1.0f + progress) * height); + canvas.translate(0, (1.0f + progress) * translationHeight); old.draw(canvas); canvas.restore(); } if (layout != null) { if (a == count - 1 || old != null) { textPaint.setAlpha((int) (255 * (1.0f + progress))); - canvas.translate(0, progress * height); + canvas.translate(0, progress * translationHeight); } else { textPaint.setAlpha(255); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java index cdf51c185..631b5ccbc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java @@ -150,7 +150,7 @@ public class ColorPicker extends FrameLayout { for (int i = 1; i < LOCATIONS.length; i++) { float value = LOCATIONS[i]; - if (value > location) { + if (value >= location) { leftIndex = i - 1; rightIndex = i; break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PathAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PathAnimator.java index 393700d65..78fb0efea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PathAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PathAnimator.java @@ -20,6 +20,7 @@ import java.util.ArrayList; public class PathAnimator { private Path path = new Path(); + private float pathTime = -1; private float scale; private float tx; private float ty; @@ -108,69 +109,72 @@ public class PathAnimator { } public void draw(Canvas canvas, Paint paint, float time) { - KeyFrame startKeyFrame = null; - KeyFrame endKeyFrame = null; - for (int a = 0, N = keyFrames.size(); a < N; a++) { - KeyFrame keyFrame = keyFrames.get(a); - if ((startKeyFrame == null || startKeyFrame.time < keyFrame.time) && keyFrame.time <= time) { - startKeyFrame = keyFrame; + if (pathTime != time) { + pathTime = time; + KeyFrame startKeyFrame = null; + KeyFrame endKeyFrame = null; + for (int a = 0, N = keyFrames.size(); a < N; a++) { + KeyFrame keyFrame = keyFrames.get(a); + if ((startKeyFrame == null || startKeyFrame.time < keyFrame.time) && keyFrame.time <= time) { + startKeyFrame = keyFrame; + } + if ((endKeyFrame == null || endKeyFrame.time > keyFrame.time) && keyFrame.time >= time) { + endKeyFrame = keyFrame; + } } - if ((endKeyFrame == null || endKeyFrame.time > keyFrame.time) && keyFrame.time >= time) { - endKeyFrame = keyFrame; + if (endKeyFrame == startKeyFrame) { + startKeyFrame = null; } - } - if (endKeyFrame == startKeyFrame) { - startKeyFrame = null; - } - if (startKeyFrame != null && endKeyFrame == null) { - endKeyFrame = startKeyFrame; - startKeyFrame = null; - } - if (endKeyFrame == null || startKeyFrame != null && startKeyFrame.commands.size() != endKeyFrame.commands.size()) { - return; - } - path.reset(); - for (int a = 0, N = endKeyFrame.commands.size(); a < N; a++) { - Object startCommand = startKeyFrame != null ? startKeyFrame.commands.get(a) : null; - Object endCommand = endKeyFrame.commands.get(a); - if (startCommand != null && startCommand.getClass() != endCommand.getClass()) { + if (startKeyFrame != null && endKeyFrame == null) { + endKeyFrame = startKeyFrame; + startKeyFrame = null; + } + if (endKeyFrame == null || startKeyFrame != null && startKeyFrame.commands.size() != endKeyFrame.commands.size()) { return; } - float progress; - if (startKeyFrame != null) { - progress = (time - startKeyFrame.time) / (endKeyFrame.time - startKeyFrame.time); - } else { - progress = 1.0f; - } - if (endCommand instanceof MoveTo) { - MoveTo end = (MoveTo) endCommand; - MoveTo start = (MoveTo) startCommand; - if (start != null) { - path.moveTo(AndroidUtilities.dp(start.x + (end.x - start.x) * progress), AndroidUtilities.dp(start.y + (end.y - start.y) * progress)); - } else { - path.moveTo(AndroidUtilities.dp(end.x), AndroidUtilities.dp(end.y)); + path.reset(); + for (int a = 0, N = endKeyFrame.commands.size(); a < N; a++) { + Object startCommand = startKeyFrame != null ? startKeyFrame.commands.get(a) : null; + Object endCommand = endKeyFrame.commands.get(a); + if (startCommand != null && startCommand.getClass() != endCommand.getClass()) { + return; } - } else if (endCommand instanceof LineTo) { - LineTo end = (LineTo) endCommand; - LineTo start = (LineTo) startCommand; - if (start != null) { - path.lineTo(AndroidUtilities.dp(start.x + (end.x - start.x) * progress), AndroidUtilities.dp(start.y + (end.y - start.y) * progress)); + float progress; + if (startKeyFrame != null) { + progress = (time - startKeyFrame.time) / (endKeyFrame.time - startKeyFrame.time); } else { - path.lineTo(AndroidUtilities.dp(end.x), AndroidUtilities.dp(end.y)); + progress = 1.0f; } - } else if (endCommand instanceof CurveTo) { - CurveTo end = (CurveTo) endCommand; - CurveTo start = (CurveTo) startCommand; - if (start != null) { - path.cubicTo(AndroidUtilities.dp(start.x1 + (end.x1 - start.x1) * progress), AndroidUtilities.dp(start.y1 + (end.y1 - start.y1) * progress), - AndroidUtilities.dp(start.x2 + (end.x2 - start.x2) * progress), AndroidUtilities.dp(start.y2 + (end.y2 - start.y2) * progress), - AndroidUtilities.dp(start.x + (end.x - start.x) * progress), AndroidUtilities.dp(start.y + (end.y - start.y) * progress)); - } else { - path.cubicTo(AndroidUtilities.dp(end.x1), AndroidUtilities.dp(end.y1), AndroidUtilities.dp(end.x2), AndroidUtilities.dp(end.y2), AndroidUtilities.dp(end.x), AndroidUtilities.dp(end.y)); + if (endCommand instanceof MoveTo) { + MoveTo end = (MoveTo) endCommand; + MoveTo start = (MoveTo) startCommand; + if (start != null) { + path.moveTo(AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress)); + } else { + path.moveTo(AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y)); + } + } else if (endCommand instanceof LineTo) { + LineTo end = (LineTo) endCommand; + LineTo start = (LineTo) startCommand; + if (start != null) { + path.lineTo(AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress)); + } else { + path.lineTo(AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y)); + } + } else if (endCommand instanceof CurveTo) { + CurveTo end = (CurveTo) endCommand; + CurveTo start = (CurveTo) startCommand; + if (start != null) { + path.cubicTo(AndroidUtilities.dpf2(start.x1 + (end.x1 - start.x1) * progress), AndroidUtilities.dpf2(start.y1 + (end.y1 - start.y1) * progress), + AndroidUtilities.dpf2(start.x2 + (end.x2 - start.x2) * progress), AndroidUtilities.dpf2(start.y2 + (end.y2 - start.y2) * progress), + AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress)); + } else { + path.cubicTo(AndroidUtilities.dpf2(end.x1), AndroidUtilities.dpf2(end.y1), AndroidUtilities.dpf2(end.x2), AndroidUtilities.dpf2(end.y2), AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y)); + } } } + path.close(); } - path.close(); canvas.drawPath(path, paint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java index c2f0af487..836a1795f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java @@ -458,6 +458,10 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView return toolsView; } + public FrameLayout getCurtainView() { + return curtainView; + } + public TextView getDoneTextView() { return doneTextView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PinnedLineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PinnedLineView.java new file mode 100644 index 000000000..fdcf1ce19 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PinnedLineView.java @@ -0,0 +1,283 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.view.View; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; + +public class PinnedLineView extends View { + + int selectedPosition = -1; + int totalCount = 0; + + int animateToPosition; + float animateFromPosition; + int animateFromTotal; + int animateToTotal; + boolean animationInProgress; + + boolean replaceInProgress; + private float startOffsetFrom; + private float startOffsetTo; + private int lineHFrom; + private int lineHTo; + + RectF rectF = new RectF(); + float animationProgress; + ValueAnimator animator; + + Paint fadePaint; + Paint fadePaint2; + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + Paint selectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private int nextPosition = -1; + private int color; + + public PinnedLineView(Context context) { + super(context); + + paint.setStyle(Paint.Style.FILL); + paint.setStrokeCap(Paint.Cap.ROUND); + + selectedPaint.setStyle(Paint.Style.FILL); + selectedPaint.setStrokeCap(Paint.Cap.ROUND); + + fadePaint = new Paint(); + LinearGradient gradient = new LinearGradient(0, 0,0, AndroidUtilities.dp(6), new int[]{0xffffffff, 0}, new float[]{0f, 1f}, Shader.TileMode.CLAMP); + fadePaint.setShader(gradient); + fadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + + fadePaint2 = new Paint(); + gradient = new LinearGradient(0, 0,0, AndroidUtilities.dp(6), new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP); + fadePaint2.setShader(gradient); + fadePaint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + + updateColors(); + } + + public void updateColors() { + color = Theme.getColor(Theme.key_chat_topPanelLine); + paint.setColor(ColorUtils.setAlphaComponent(color, (int) ((Color.alpha(color) / 255f) * 112))); + selectedPaint.setColor(Theme.getColor(Theme.key_chat_topPanelLine)); + } + + private void selectPosition(int position) { + if (replaceInProgress) { + nextPosition = position; + return; + } + if (animationInProgress) { + if (animateToPosition == position) { + return; + } + if (animator != null) { + animator.cancel(); + } + animateFromPosition = animateFromPosition * (1f - animationProgress) + animateToPosition * animationProgress; + } else { + animateFromPosition = selectedPosition; + } + if (position != selectedPosition) { + animateToPosition = position; + animationInProgress = true; + animationProgress = 0; + invalidate(); + animator = ValueAnimator.ofFloat(0, 1f); + animator.addUpdateListener(valueAnimator -> { + animationProgress = (float) valueAnimator.getAnimatedValue(); + invalidate(); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animationInProgress = false; + selectedPosition = animateToPosition; + invalidate(); + if (nextPosition >= 0) { + selectPosition(nextPosition); + nextPosition = -1; + } + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setDuration(220); + animator.start(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (selectedPosition < 0 || totalCount == 0) { + return; + } + boolean drawFade = (replaceInProgress ? Math.max(animateFromTotal, animateToTotal) : totalCount) > 3; + if (drawFade) { + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG); + } + int viewPadding = AndroidUtilities.dp(8); + float lineH; + if (replaceInProgress) { + lineH = lineHFrom * (1f - animationProgress) + lineHTo * animationProgress; + } else { + if (totalCount == 0) { + return; + } + lineH = (getMeasuredHeight() - viewPadding * 2) / (float) (Math.min(totalCount, 3)); + } + if (lineH == 0) { + return; + } + float linePadding = AndroidUtilities.dpf2(0.7f); + + float startOffset; + if (replaceInProgress) { + startOffset = startOffsetFrom * (1f - animationProgress) + startOffsetTo * animationProgress; + } else { + if (animationInProgress) { + float offset1 = (animateFromPosition - 1) * lineH; + float offset2 = (animateToPosition - 1) * lineH; + startOffset = offset1 * (1f - animationProgress) + offset2 * animationProgress; + } else { + startOffset = (selectedPosition - 1) * lineH; + } + + if (startOffset < 0) { + startOffset = 0; + } else if (viewPadding + (totalCount - 1) * lineH - startOffset < getMeasuredHeight() - viewPadding - lineH) { + startOffset = (viewPadding + (totalCount - 1) * lineH) - (getMeasuredHeight() - viewPadding - lineH); + } + } + + float r = getMeasuredWidth() / 2f; + + int start = Math.max(0, (int) ((viewPadding + startOffset) / lineH - 1)); + int end = Math.min(start + 6, replaceInProgress ? Math.max(animateFromTotal, animateToTotal) : totalCount); + for (int i = start; i < end; i++) { + float startY = viewPadding + i * lineH - startOffset; + if (startY + lineH < 0 || startY > getMeasuredHeight()) { + continue; + } + rectF.set(0, startY + linePadding, getMeasuredWidth(), startY + lineH - linePadding); + if (replaceInProgress && i >= animateToTotal) { + paint.setColor(ColorUtils.setAlphaComponent(color, (int) ((Color.alpha(color) / 255f) * 76 * (1f - animationProgress)))); + canvas.drawRoundRect(rectF, r, r, paint); + paint.setColor(ColorUtils.setAlphaComponent(color, (int) ((Color.alpha(color) / 255f) * 76))); + } else if (replaceInProgress && i >= animateFromTotal) { + paint.setColor(ColorUtils.setAlphaComponent(color, (int) ((Color.alpha(color) / 255f) * 76 * animationProgress))); + canvas.drawRoundRect(rectF, r, r, paint); + paint.setColor(ColorUtils.setAlphaComponent(color, (int) ((Color.alpha(color) / 255f) * 76))); + } else { + canvas.drawRoundRect(rectF, r, r, paint); + } + + } + + if (animationInProgress) { + float startY = viewPadding + (animateFromPosition * (1f - animationProgress) + animateToPosition * animationProgress) * lineH - startOffset; + rectF.set(0, startY + linePadding, getMeasuredWidth(), startY + lineH - linePadding); + canvas.drawRoundRect(rectF, r, r, selectedPaint); + } else { + float startY = viewPadding + selectedPosition * lineH - startOffset; + rectF.set(0, startY + linePadding, getMeasuredWidth(), startY + lineH - linePadding); + canvas.drawRoundRect(rectF, r, r, selectedPaint); + } + + if (drawFade) { + canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(6), fadePaint); + canvas.drawRect(0, getMeasuredHeight() - AndroidUtilities.dp(6), getMeasuredWidth(), getMeasuredHeight(), fadePaint); + + canvas.translate(0, getMeasuredHeight() - AndroidUtilities.dp(6)); + canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(6), fadePaint2); + } + } + + public void set(int position, int totalCount, boolean animated) { + if (selectedPosition < 0 || totalCount == 0 || this.totalCount == 0) { + animated = false; + } + if (!animated) { + if (animator != null) { + animator.cancel(); + } + this.selectedPosition = position; + this.totalCount = totalCount; + invalidate(); + } else { + if (this.totalCount != totalCount || Math.abs(selectedPosition - position) > 2) { + if (animator != null) { + animator.cancel(); + } + int viewPadding = AndroidUtilities.dp(8); + lineHFrom = (getMeasuredHeight() - viewPadding * 2) / (Math.min(this.totalCount, 3)); + lineHTo = (getMeasuredHeight() - viewPadding * 2) / (Math.min(totalCount, 3)); + + startOffsetFrom = (selectedPosition - 1) * lineHFrom; + if (startOffsetFrom < 0) { + startOffsetFrom = 0; + } else if (viewPadding + (this.totalCount - 1) * lineHFrom - startOffsetFrom < getMeasuredHeight() - viewPadding - lineHFrom) { + startOffsetFrom = (viewPadding + (this.totalCount - 1) * lineHFrom) - (getMeasuredHeight() - viewPadding - lineHFrom); + } + + startOffsetTo = (position - 1) * lineHTo; + if (startOffsetTo < 0) { + startOffsetTo = 0; + } else if (viewPadding + (totalCount - 1) * lineHTo - startOffsetTo < getMeasuredHeight() - viewPadding - lineHTo) { + startOffsetTo = (viewPadding + (totalCount - 1) * lineHTo) - (getMeasuredHeight() - viewPadding - lineHTo); + } + animateFromPosition = selectedPosition; + animateToPosition = position; + + selectedPosition = position; + animateFromTotal = this.totalCount; + animateToTotal = totalCount; + this.totalCount = totalCount; + + replaceInProgress = true; + animationInProgress = true; + animationProgress = 0; + + invalidate(); + animator = ValueAnimator.ofFloat(0, 1f); + animator.addUpdateListener(valueAnimator -> { + animationProgress = (float) valueAnimator.getAnimatedValue(); + invalidate(); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + replaceInProgress = false; + animationInProgress = false; + invalidate(); + if (nextPosition >= 0) { + selectPosition(nextPosition); + nextPosition = -1; + } + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setDuration(220); + animator.start(); + } else { + selectPosition(position); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayPauseDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayPauseDrawable.java new file mode 100644 index 000000000..12ca076ca --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayPauseDrawable.java @@ -0,0 +1,115 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.view.animation.AnimationUtils; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; + +public class PlayPauseDrawable extends Drawable { + + private final Paint paint; + private final int size; + + private boolean pause; + private float progress; + private long lastUpdateTime; + + public PlayPauseDrawable(int size) { + this.size = AndroidUtilities.dp(size); + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.WHITE); + } + + @Override + public void draw(@NonNull Canvas canvas) { + long newUpdateTime = AnimationUtils.currentAnimationTimeMillis(); + long dt = newUpdateTime - lastUpdateTime; + lastUpdateTime = newUpdateTime; + if (dt > 18) { + dt = 16; + } + if (pause && progress < 1f) { + progress += dt / 300f; + if (progress >= 1f) { + progress = 1f; + } else { + invalidateSelf(); + } + } else if (!pause && progress > 0f) { + progress -= dt / 300f; + if (progress <= 0f) { + progress = 0f; + } else { + invalidateSelf(); + } + } + final Rect bounds = getBounds(); + canvas.save(); + canvas.translate(bounds.centerX() + AndroidUtilities.dp(1) * (1.0f - progress), bounds.centerY()); + final float ms = 500.0f * progress; + final float rotation; + if (ms < 100) { + rotation = -5 * CubicBezierInterpolator.EASE_BOTH.getInterpolation(ms / 100.0f); + } else if (ms < 484) { + rotation = -5 + 95 * CubicBezierInterpolator.EASE_BOTH.getInterpolation((ms - 100) / 384); + } else { + rotation = 90; + } + canvas.scale(1.45f * size / AndroidUtilities.dp(28), 1.5f * size / AndroidUtilities.dp(28)); + canvas.rotate(rotation); + Theme.playPauseAnimator.draw(canvas, paint, ms); + canvas.scale(1.0f, -1.0f); + Theme.playPauseAnimator.draw(canvas, paint, ms); + canvas.restore(); + } + + public void setPause(boolean pause) { + setPause(pause, true); + } + + public void setPause(boolean pause, boolean animated) { + if (this.pause != pause) { + this.pause = pause; + if (!animated) { + progress = pause ? 1f : 0f; + } + this.lastUpdateTime = AnimationUtils.currentAnimationTimeMillis(); + invalidateSelf(); + } + } + + @Override + public void setAlpha(int i) { + paint.setAlpha(i); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + paint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicWidth() { + return size; + } + + @Override + public int getIntrinsicHeight() { + return size; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java index 28b912a0f..461697380 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java @@ -29,11 +29,20 @@ public class PlayingGameDrawable extends StatusDrawable { private boolean started = false; private RectF rect = new RectF(); private float progress; + private final boolean isDialogScreen; + public PlayingGameDrawable(boolean isDialogScreen) { + this.isDialogScreen = isDialogScreen; + } public void setIsChat(boolean value) { isChat = value; } + @Override + public void setColor(int color) { + + } + private void update() { long newTime = System.currentTimeMillis(); long dt = newTime - lastUpdateTime; @@ -73,7 +82,7 @@ public class PlayingGameDrawable extends StatusDrawable { //y = AndroidUtilities.dp(9.3f) + getBounds().top; } - paint.setColor(Theme.getColor(Theme.key_chat_status)); + paint.setColor(Theme.getColor(isDialogScreen ? Theme.key_chats_actionMessage : Theme.key_chat_status)); rect.set(0, y, size, y + size); int rad; if (progress < 0.5f) { @@ -98,7 +107,7 @@ public class PlayingGameDrawable extends StatusDrawable { } paint.setAlpha(255); canvas.drawArc(rect, rad, 360 - rad * 2, true, paint); - paint.setColor(Theme.getColor(Theme.key_actionBarDefault)); + paint.setColor(Theme.getColor(isDialogScreen ? Theme.key_windowBackgroundWhite : Theme.key_actionBarDefault)); canvas.drawCircle(AndroidUtilities.dp(4), y + size / 2 - AndroidUtilities.dp(2), AndroidUtilities.dp(1), paint); checkUpdate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java new file mode 100644 index 000000000..a68142226 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java @@ -0,0 +1,651 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.animation.Interpolator; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; + +import java.util.Locale; + +public class ProximitySheet extends FrameLayout { + + private VelocityTracker velocityTracker = null; + private int startedTrackingX; + private int startedTrackingY; + private int startedTrackingPointerId = -1; + private boolean maybeStartTracking = false; + private boolean startedTracking = false; + private AnimatorSet currentAnimation = null; + private android.graphics.Rect rect = new Rect(); + private Paint backgroundPaint = new Paint(); + + private boolean dismissed; + + private AnimatorSet currentSheetAnimation; + private int currentSheetAnimationType; + + private ViewGroup containerView; + + private boolean useHardwareLayer = true; + + private int backgroundPaddingTop; + private int backgroundPaddingLeft; + + private int touchSlop; + private boolean useFastDismiss; + private Interpolator openInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; + + private NumberPicker kmPicker; + private NumberPicker mPicker; + private onRadiusPickerChange onRadiusChange; + private TextView buttonTextView; + private TextView infoTextView; + private boolean radiusSet; + private TLRPC.User currentUser; + private int totalWidth; + private boolean useImperialSystem; + + private LinearLayout customView; + + private Runnable onDismissCallback; + + public interface onRadiusPickerChange { + boolean run(boolean move, int param); + } + + public ProximitySheet(Context context, TLRPC.User user, onRadiusPickerChange onRadius, onRadiusPickerChange onFinish, Runnable onDismiss) { + super(context); + setWillNotDraw(false); + onDismissCallback = onDismiss; + + ViewConfiguration vc = ViewConfiguration.get(context); + touchSlop = vc.getScaledTouchSlop(); + + Rect padding = new Rect(); + Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.getPadding(padding); + backgroundPaddingLeft = padding.left; + + containerView = new FrameLayout(getContext()) { + @Override + public boolean hasOverlappingRendering() { + return false; + } + }; + containerView.setBackgroundDrawable(shadowDrawable); + containerView.setPadding(backgroundPaddingLeft, AndroidUtilities.dp(8) + padding.top - 1, backgroundPaddingLeft, 0); + + containerView.setVisibility(View.INVISIBLE); + addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + + useImperialSystem = LocaleController.getUseImperialSystemType(); + currentUser = user; + + onRadiusChange = onRadius; + + kmPicker = new NumberPicker(context); + kmPicker.setTextOffset(AndroidUtilities.dp(10)); + kmPicker.setItemCount(5); + mPicker = new NumberPicker(context); + mPicker.setItemCount(5); + mPicker.setTextOffset(-AndroidUtilities.dp(10)); + + customView = new LinearLayout(context) { + + boolean ignoreLayout = false; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + ignoreLayout = true; + int count; + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + count = 3; + } else { + count = 5; + } + kmPicker.setItemCount(count); + mPicker.setItemCount(count); + kmPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count; + mPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count; + ignoreLayout = false; + int prewWidth = 0; + totalWidth = MeasureSpec.getSize(widthMeasureSpec); + if (prewWidth != totalWidth) { + updateText(false, false); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + customView.setOrientation(LinearLayout.VERTICAL); + + FrameLayout titleLayout = new FrameLayout(context); + customView.addView(titleLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 0, 0, 4)); + + TextView titleView = new TextView(context); + titleView.setText(LocaleController.getString("LocationNotifiation", R.string.LocationNotifiation)); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 12, 0, 0)); + titleView.setOnTouchListener((v, event) -> true); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + linearLayout.setWeightSum(1.0f); + customView.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + long currentTime = System.currentTimeMillis(); + + FrameLayout buttonContainer = new FrameLayout(context); + + infoTextView = new TextView(context); + + buttonTextView = new TextView(context) { + @Override + public CharSequence getAccessibilityClassName() { + return Button.class.getName(); + } + }; + + linearLayout.addView(kmPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f)); + kmPicker.setFormatter(value -> { + if (useImperialSystem) { + return LocaleController.formatString("MilesShort", R.string.MilesShort, value); + } else { + return LocaleController.formatString("KMetersShort", R.string.KMetersShort, value); + } + }); + kmPicker.setMinValue(0); + kmPicker.setMaxValue(10); + kmPicker.setWrapSelectorWheel(false); + kmPicker.setTextOffset(AndroidUtilities.dp(20)); + final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> { + try { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) { + + } + updateText(true, true); + }; + kmPicker.setOnValueChangedListener(onValueChangeListener); + + mPicker.setMinValue(0); + mPicker.setMaxValue(10); + mPicker.setWrapSelectorWheel(false); + mPicker.setTextOffset(-AndroidUtilities.dp(20)); + linearLayout.addView(mPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f)); + mPicker.setFormatter(value -> { + if (useImperialSystem) { + if (value == 1) { + return LocaleController.formatString("FootsShort", R.string.FootsShort, 250); + } else { + if (value > 1) { + value--; + } + return String.format(Locale.US, ".%d", value); + } + } else { + if (value == 1) { + return LocaleController.formatString("MetersShort", R.string.MetersShort, 50); + } else { + if (value > 1) { + value--; + } + return LocaleController.formatString("MetersShort", R.string.MetersShort, value * 100); + } + } + }); + mPicker.setOnValueChangedListener(onValueChangeListener); + + kmPicker.setValue(0); + mPicker.setValue(6); + + customView.addView(buttonContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16)); + + buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonContainer.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + buttonTextView.setOnClickListener(v -> { + if (buttonTextView.getTag() != null) { + return; + } + float value = getValue(); + if (onFinish.run(true, (int) Math.max(1, value))) { + dismiss(); + } + }); + + infoTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + infoTextView.setGravity(Gravity.CENTER); + infoTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2)); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + infoTextView.setAlpha(0.0f); + infoTextView.setScaleX(0.5f); + infoTextView.setScaleY(0.5f); + buttonContainer.addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + + containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + } + + public View getCustomView() { + return customView; + } + + public float getValue() { + float value = kmPicker.getValue() * 1000; + int second = mPicker.getValue(); + if (useImperialSystem) { + if (second == 1) { + value += 47.349f; + } else { + if (second > 1) { + second--; + } + value += second * 100; + } + } else { + if (second == 1) { + value += 50; + } else { + if (second > 1) { + second--; + } + value += second * 100; + } + } + if (useImperialSystem) { + value *= 1.60934f; + } + return value; + } + + public boolean getRadiusSet() { + return radiusSet; + } + + public void setRadiusSet() { + radiusSet = true; + } + + public void updateText(boolean move, boolean animated) { + float value = getValue(); + String distance = LocaleController.formatDistance(value, 2, useImperialSystem); + if (onRadiusChange.run(move, (int) value) || currentUser == null) { + if (currentUser == null) { + buttonTextView.setText(LocaleController.formatString("LocationNotifiationButtonGroup", R.string.LocationNotifiationButtonGroup, distance)); + } else { + String format = LocaleController.getString("LocationNotifiationButtonUser", R.string.LocationNotifiationButtonUser); + int width = (int) Math.ceil(buttonTextView.getPaint().measureText(format)); + int restWidth = totalWidth - AndroidUtilities.dp(32 + 62) - width; + CharSequence name = TextUtils.ellipsize(UserObject.getFirstName(currentUser), buttonTextView.getPaint(), restWidth, TextUtils.TruncateAt.END); + buttonTextView.setText(LocaleController.formatString("LocationNotifiationButtonUser", R.string.LocationNotifiationButtonUser, name, distance)); + } + if (buttonTextView.getTag() != null) { + buttonTextView.setTag(null); + buttonTextView.animate().setDuration(180).alpha(1.0f).scaleX(1.0f).scaleY(1.0f).start(); + infoTextView.animate().setDuration(180).alpha(0.0f).scaleX(0.5f).scaleY(0.5f).start(); + } + } else { + infoTextView.setText(LocaleController.formatString("LocationNotifiationCloser", R.string.LocationNotifiationCloser, distance)); + if (buttonTextView.getTag() == null) { + buttonTextView.setTag(1); + buttonTextView.animate().setDuration(180).alpha(0.0f).scaleX(0.5f).scaleY(0.5f).start(); + infoTextView.animate().setDuration(180).alpha(1.0f).scaleX(1.0f).scaleY(1.0f).start(); + } + } + } + + private void checkDismiss(float velX, float velY) { + float translationY = containerView.getTranslationY(); + boolean backAnimation = translationY < AndroidUtilities.getPixelsInCM(0.8f, false) && (velY < 3500 || Math.abs(velY) < Math.abs(velX)) || velY < 0 && Math.abs(velY) >= 3500; + if (!backAnimation) { + useFastDismiss = true; + dismiss(); + } else { + currentAnimation = new AnimatorSet(); + currentAnimation.playTogether(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0)); + currentAnimation.setDuration((int) (150 * (Math.max(0, translationY) / AndroidUtilities.getPixelsInCM(0.8f, false)))); + currentAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); + currentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (currentAnimation != null && currentAnimation.equals(animation)) { + currentAnimation = null; + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); + } + }); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + currentAnimation.start(); + } + } + + private void cancelCurrentAnimation() { + if (currentAnimation != null) { + currentAnimation.cancel(); + currentAnimation = null; + } + } + + boolean processTouchEvent(MotionEvent ev, boolean intercept) { + if (dismissed) { + return false; + } + if (ev != null && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) && (!startedTracking && !maybeStartTracking && ev.getPointerCount() == 1)) { + startedTrackingX = (int) ev.getX(); + startedTrackingY = (int) ev.getY(); + if (startedTrackingY < containerView.getTop() || startedTrackingX < containerView.getLeft() || startedTrackingX > containerView.getRight()) { + requestDisallowInterceptTouchEvent(true); + dismiss(); + return true; + } + startedTrackingPointerId = ev.getPointerId(0); + maybeStartTracking = true; + cancelCurrentAnimation(); + if (velocityTracker != null) { + velocityTracker.clear(); + } + } else if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && ev.getPointerId(0) == startedTrackingPointerId) { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + float dx = Math.abs((int) (ev.getX() - startedTrackingX)); + float dy = (int) ev.getY() - startedTrackingY; + velocityTracker.addMovement(ev); + if (maybeStartTracking && !startedTracking && (dy > 0 && dy / 3.0f > Math.abs(dx) && Math.abs(dy) >= touchSlop)) { + startedTrackingY = (int) ev.getY(); + maybeStartTracking = false; + startedTracking = true; + requestDisallowInterceptTouchEvent(true); + } else if (startedTracking) { + float translationY = containerView.getTranslationY(); + translationY += dy; + if (translationY < 0) { + translationY = 0; + } + containerView.setTranslationY(translationY); + startedTrackingY = (int) ev.getY(); + } + } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + velocityTracker.computeCurrentVelocity(1000); + float translationY = containerView.getTranslationY(); + if (startedTracking || translationY != 0) { + checkDismiss(velocityTracker.getXVelocity(), velocityTracker.getYVelocity()); + startedTracking = false; + } else { + maybeStartTracking = false; + startedTracking = false; + } + if (velocityTracker != null) { + velocityTracker.recycle(); + velocityTracker = null; + } + startedTrackingPointerId = -1; + } + return !intercept && maybeStartTracking || startedTracking; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return dismissed || processTouchEvent(ev, false); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + View rootView = getRootView(); + getWindowVisibleDisplayFrame(rect); + + setMeasuredDimension(width, height); + + containerView.measure(MeasureSpec.makeMeasureSpec(width + backgroundPaddingLeft * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child.getVisibility() == GONE || child == containerView) { + continue; + } + measureChildWithMargins(child, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 0, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY), 0); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int t = (bottom - top) - containerView.getMeasuredHeight(); + int l = ((right - left) - containerView.getMeasuredWidth()) / 2; + containerView.layout(l, t, l + containerView.getMeasuredWidth(), t + containerView.getMeasuredHeight()); + + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE || child == containerView) { + continue; + } + + final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams(); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + int childLeft; + int childTop; + + int gravity = lp.gravity; + if (gravity == -1) { + gravity = Gravity.TOP | Gravity.LEFT; + } + + final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = (right - left - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = right - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.CENTER_VERTICAL: + childTop = (bottom - top - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = (bottom - top) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return dismissed || processTouchEvent(event, true); + } + + @Override + public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { + if (maybeStartTracking && !startedTracking) { + onTouchEvent(null); + } + super.requestDisallowInterceptTouchEvent(disallowIntercept); + } + + @Override + public boolean hasOverlappingRendering() { + return false; + } + + public void show() { + dismissed = false; + cancelSheetAnimation(); + containerView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x + backgroundPaddingLeft * 2, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, View.MeasureSpec.AT_MOST)); + startOpenAnimation(); + updateText(true, false); + } + + private void cancelSheetAnimation() { + if (currentSheetAnimation != null) { + currentSheetAnimation.cancel(); + currentSheetAnimation = null; + currentSheetAnimationType = 0; + } + } + + private void startOpenAnimation() { + if (dismissed) { + return; + } + containerView.setVisibility(View.VISIBLE); + + if (Build.VERSION.SDK_INT >= 20 && useHardwareLayer) { + setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + containerView.setTranslationY(containerView.getMeasuredHeight()); + currentSheetAnimationType = 1; + currentSheetAnimation = new AnimatorSet(); + currentSheetAnimation.playTogether(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0)); + currentSheetAnimation.setDuration(400); + currentSheetAnimation.setStartDelay(20); + currentSheetAnimation.setInterpolator(openInterpolator); + currentSheetAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + if (useHardwareLayer) { + setLayerType(View.LAYER_TYPE_NONE, null); + } + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); + } + + @Override + public void onAnimationCancel(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + } + } + }); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + currentSheetAnimation.start(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (dismissed) { + return true; + } + return super.dispatchTouchEvent(ev); + } + + public void dismiss() { + if (dismissed) { + return; + } + dismissed = true; + cancelSheetAnimation(); + + currentSheetAnimationType = 2; + currentSheetAnimation = new AnimatorSet(); + currentSheetAnimation.playTogether(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, containerView.getMeasuredHeight() + AndroidUtilities.dp(10))); + if (useFastDismiss) { + int height = containerView.getMeasuredHeight(); + currentSheetAnimation.setDuration(Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height))); + useFastDismiss = false; + } else { + currentSheetAnimation.setDuration(250); + } + currentSheetAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + currentSheetAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + AndroidUtilities.runOnUIThread(() -> { + try { + dismissInternal(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); + } + + @Override + public void onAnimationCancel(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + } + } + }); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + currentSheetAnimation.start(); + } + + private void dismissInternal() { + if (getParent() instanceof ViewGroup) { + ViewGroup parent = (ViewGroup) getParent(); + parent.removeView(this); + } + onDismissCallback.run(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java index 5718fbddf..55a10d749 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -43,19 +43,19 @@ import java.util.concurrent.TimeUnit; public class RLottieDrawable extends BitmapDrawable implements Animatable { public static native long create(String src, int w, int h, int[] params, boolean precache, int[] colorReplacement, boolean limitFps); - private static native long createWithJson(String json, String name, int[] params, int[] colorReplacement); + protected static native long createWithJson(String json, String name, int[] params, int[] colorReplacement); public static native void destroy(long ptr); private static native void setLayerColor(long ptr, String layer, int color); private static native void replaceColors(long ptr, int[] colorReplacement); - public static native int getFrame(long ptr, int frame, Bitmap bitmap, int w, int h, int stride); + public static native int getFrame(long ptr, int frame, Bitmap bitmap, int w, int h, int stride, boolean clear); private static native void createCache(long ptr, int w, int h); - private int width; - private int height; - private final int[] metaData = new int[3]; - private int timeBetweenFrames; - private int customEndFrame = -1; - private boolean playInDirectionOfCustomEndFrame; + protected int width; + protected int height; + protected final int[] metaData = new int[3]; + protected int timeBetweenFrames; + protected int customEndFrame = -1; + protected boolean playInDirectionOfCustomEndFrame; private int[] newReplaceColors; private int[] pendingReplaceColors; private HashMap newColorUpdates = new HashMap<>(); @@ -63,51 +63,51 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { private HashMap vibrationPattern; private WeakReference frameReadyCallback; - private WeakReference onFinishCallback; + protected WeakReference onFinishCallback; private int finishFrame; private View currentParentView; - private int isDice; - private int diceSwitchFramesCount = -1; + protected int isDice; + protected int diceSwitchFramesCount = -1; - private int autoRepeat = 1; - private int autoRepeatPlayCount; + protected int autoRepeat = 1; + protected int autoRepeatPlayCount; private long lastFrameTime; - private volatile boolean nextFrameIsLast; + protected volatile boolean nextFrameIsLast; - private Runnable cacheGenerateTask; - private Runnable loadFrameTask; - private volatile Bitmap renderingBitmap; - private volatile Bitmap nextRenderingBitmap; - private volatile Bitmap backgroundBitmap; - private boolean waitingForNextTask; + protected Runnable cacheGenerateTask; + protected Runnable loadFrameTask; + protected volatile Bitmap renderingBitmap; + protected volatile Bitmap nextRenderingBitmap; + protected volatile Bitmap backgroundBitmap; + protected boolean waitingForNextTask; - private CountDownLatch frameWaitSync; + protected CountDownLatch frameWaitSync; - private boolean destroyWhenDone; + protected boolean destroyWhenDone; private boolean decodeSingleFrame; private boolean singleFrameDecoded; private boolean forceFrameRedraw; private boolean applyingLayerColors; - private int currentFrame; + protected int currentFrame; private boolean shouldLimitFps; private float scaleX = 1.0f; private float scaleY = 1.0f; private boolean applyTransformation; private final Rect dstRect = new Rect(); - private static final Handler uiHandler = new Handler(Looper.getMainLooper()); - private volatile boolean isRunning; - private volatile boolean isRecycled; - private volatile long nativePtr; - private volatile long secondNativePtr; - private boolean loadingInBackground; - private boolean secondLoadingInBackground; - private boolean destroyAfterLoading; - private int secondFramesCount; - private volatile boolean setLastFrame; + protected static final Handler uiHandler = new Handler(Looper.getMainLooper()); + protected volatile boolean isRunning; + protected volatile boolean isRecycled; + protected volatile long nativePtr; + protected volatile long secondNativePtr; + protected boolean loadingInBackground; + protected boolean secondLoadingInBackground; + protected boolean destroyAfterLoading; + protected int secondFramesCount; + protected volatile boolean setLastFrame; private boolean invalidateOnProgressSet; private boolean isInvalid; @@ -120,7 +120,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { private static DispatchQueuePool loadFrameRunnableQueue = new DispatchQueuePool(4); private static ThreadPoolExecutor lottieCacheGenerateQueue; - private Runnable uiRunnableNoFrame = new Runnable() { + protected Runnable uiRunnableNoFrame = new Runnable() { @Override public void run() { loadFrameTask = null; @@ -136,7 +136,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } }; - private Runnable uiRunnable = new Runnable() { + protected Runnable uiRunnable = new Runnable() { @Override public void run() { singleFrameDecoded = true; @@ -171,7 +171,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } }; - private void checkRunningTasks() { + protected void checkRunningTasks() { if (cacheGenerateTask != null) { if (lottieCacheGenerateQueue.remove(cacheGenerateTask)) { cacheGenerateTask = null; @@ -183,7 +183,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } } - private void decodeFrameFinishedInternal() { + protected void decodeFrameFinishedInternal() { if (destroyWhenDone) { checkRunningTasks(); if (loadFrameTask == null && cacheGenerateTask == null && nativePtr != 0) { @@ -206,7 +206,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { scheduleNextGetFrame(); } - private void recycleResources() { + protected void recycleResources() { if (renderingBitmap != null) { renderingBitmap.recycle(); renderingBitmap = null; @@ -226,7 +226,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } } - private Runnable loadFrameRunnable = new Runnable() { + protected Runnable loadFrameRunnable = new Runnable() { @Override public void run() { if (isRecycled) { @@ -273,7 +273,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } else { ptrToUse = nativePtr; } - int result = getFrame(ptrToUse, currentFrame, backgroundBitmap, width, height, backgroundBitmap.getRowBytes()); + int result = getFrame(ptrToUse, currentFrame, backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), true); if (result == -1) { uiHandler.post(uiRunnableNoFrame); if (frameWaitSync != null) { @@ -424,10 +424,8 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { return; } timeBetweenFrames = Math.max(16, (int) (1000.0f / metaData[1])); - if (isRunning) { - scheduleNextGetFrame(); - invalidateInternal(); - } + scheduleNextGetFrame(); + invalidateInternal(); }); }); @@ -471,10 +469,8 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } secondFramesCount = metaData2[0]; timeBetweenFrames = Math.max(16, (int) (1000.0f / metaData2[1])); - if (isRunning) { - scheduleNextGetFrame(); - invalidateInternal(); - } + scheduleNextGetFrame(); + invalidateInternal(); }); }); return true; @@ -496,7 +492,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } } - private String readRes(File path, int rawRes) { + public static String readRes(File path, int rawRes) { int totalRead = 0; byte[] readBuffer = readBufferLocal.get(); if (readBuffer == null) { @@ -592,7 +588,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } } - private boolean hasParentView() { + protected boolean hasParentView() { if (getCallback() != null) { return true; } @@ -609,7 +605,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { return false; } - private void invalidateInternal() { + protected void invalidateInternal() { for (int a = 0, N = parentViews.size(); a < N; a++) { View view = parentViews.get(a).get(); if (view != null) { @@ -750,7 +746,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { invalidateInternal(); } - private boolean scheduleNextGetFrame() { + protected boolean scheduleNextGetFrame() { if (loadFrameTask != null || nextRenderingBitmap != null || nativePtr == 0 || loadingInBackground || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded)) { return false; } @@ -766,6 +762,10 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { return true; } + public boolean isHeavyDrawable() { + return isDice == 0; + } + @Override public void stop() { isRunning = false; @@ -926,6 +926,27 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { if (nativePtr == 0 || destroyWhenDone) { return; } + updateCurrentFrame(); + + if (!isInvalid && renderingBitmap != null) { + if (applyTransformation) { + dstRect.set(getBounds()); + scaleX = (float) dstRect.width() / width; + scaleY = (float) dstRect.height() / height; + applyTransformation = false; + } + canvas.save(); + canvas.translate(dstRect.left, dstRect.top); + canvas.scale(scaleX, scaleY); + canvas.drawBitmap(renderingBitmap, 0, 0, getPaint()); + if (isRunning) { + invalidateInternal(); + } + canvas.restore(); + } + } + + public void updateCurrentFrame() { long now = SystemClock.elapsedRealtime(); long timeDiff = Math.abs(now - lastFrameTime); int timeCheck; @@ -949,23 +970,6 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } else if ((forceFrameRedraw || decodeSingleFrame && timeDiff >= timeCheck) && nextRenderingBitmap != null) { setCurrentFrame(now, timeDiff, timeCheck, true); } - - if (!isInvalid && renderingBitmap != null) { - if (applyTransformation) { - dstRect.set(getBounds()); - scaleX = (float) dstRect.width() / width; - scaleY = (float) dstRect.height() / height; - applyTransformation = false; - } - canvas.save(); - canvas.translate(dstRect.left, dstRect.top); - canvas.scale(scaleX, scaleY); - canvas.drawBitmap(renderingBitmap, 0, 0, getPaint()); - if (isRunning) { - invalidateInternal(); - } - canvas.restore(); - } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java index d8e43a972..128da960d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java @@ -39,11 +39,15 @@ public class RadialProgress2 { private Paint circleMiniPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private MediaActionDrawable mediaActionDrawable; private MediaActionDrawable miniMediaActionDrawable; + private float miniIconScale = 1.0f; private int circleColor; private int circlePressedColor; private int iconColor; private int iconPressedColor; private String circleColorKey; + private String circleCrossfadeColorKey; + private float circleCrossfadeColorProgress; + private float circleCheckProgress = 1.0f; private String circlePressedColorKey; private String iconColorKey; private String iconPressedColorKey; @@ -134,6 +138,16 @@ public class RadialProgress2 { iconPressedColorKey = iconPressed; } + public void setCircleCrossfadeColor(String color, float progress, float checkProgress) { + circleCrossfadeColorKey = color; + circleCrossfadeColorProgress = progress; + circleCheckProgress = checkProgress; + miniIconScale = 1.0f; + if (color != null) { + initMiniIcons(); + } + } + public void setDrawBackground(boolean value) { drawBackground = value; } @@ -191,6 +205,10 @@ public class RadialProgress2 { } } + public void setMiniIconScale(float scale) { + miniIconScale = scale; + } + public void setMiniIcon(int icon, boolean ifSame, boolean animated) { if (icon != MediaActionDrawable.ICON_DOWNLOAD && icon != MediaActionDrawable.ICON_CANCEL && icon != MediaActionDrawable.ICON_NONE) { return; @@ -268,7 +286,7 @@ public class RadialProgress2 { wholeAlpha = currentIcon != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - mediaActionDrawable.getTransitionProgress(); } - if (isPressedMini) { + if (isPressedMini && circleCrossfadeColorKey == null) { if (iconPressedColorKey != null) { miniMediaActionDrawable.setColor(Theme.getColor(iconPressedColorKey)); } else { @@ -286,7 +304,11 @@ public class RadialProgress2 { miniMediaActionDrawable.setColor(iconColor); } if (circleColorKey != null) { - circleMiniPaint.setColor(Theme.getColor(circleColorKey)); + if (circleCrossfadeColorKey != null) { + circleMiniPaint.setColor(AndroidUtilities.getOffsetColor(Theme.getColor(circleColorKey), Theme.getColor(circleCrossfadeColorKey), circleCrossfadeColorProgress, circleCheckProgress)); + } else { + circleMiniPaint.setColor(Theme.getColor(circleColorKey)); + } } else { circleMiniPaint.setColor(circleColor); } @@ -320,7 +342,7 @@ public class RadialProgress2 { circlePaint.setColor(circleColor); } } - if (drawMiniIcon && miniDrawCanvas != null) { + if ((drawMiniIcon || circleCrossfadeColorKey != null) && miniDrawCanvas != null) { miniDrawBitmap.eraseColor(0); } @@ -332,7 +354,7 @@ public class RadialProgress2 { boolean drawCircle = true; int centerX; int centerY; - if (drawMiniIcon && miniDrawCanvas != null) { + if ((drawMiniIcon || circleCrossfadeColorKey != null) && miniDrawCanvas != null) { centerX = (int) Math.ceil(progressRect.width() / 2); centerY = (int) Math.ceil(progressRect.height() / 2); } else { @@ -364,8 +386,14 @@ public class RadialProgress2 { overlayImageView.setImageCoords(centerX - circleRadius, centerY - circleRadius, circleRadius * 2, circleRadius * 2); } + int restore = Integer.MIN_VALUE; + if (miniDrawCanvas != null && circleCrossfadeColorKey != null && circleCheckProgress != 1.0f) { + restore = miniDrawCanvas.save(); + float scale = 1.0f - 0.1f * (1.0f - circleCheckProgress); + miniDrawCanvas.scale(scale, scale, centerX, centerY); + } if (drawCircle && drawBackground) { - if (drawMiniIcon && miniDrawCanvas != null) { + if ((drawMiniIcon || circleCrossfadeColorKey != null) && miniDrawCanvas != null) { miniDrawCanvas.drawCircle(centerX, centerY, circleRadius, circlePaint); } else { if (currentIcon != MediaActionDrawable.ICON_NONE || wholeAlpha != 0) { @@ -380,7 +408,7 @@ public class RadialProgress2 { if (overlayImageView.hasBitmapImage()) { overlayImageView.setAlpha(wholeAlpha * overrideAlpha); - if (drawMiniIcon && miniDrawCanvas != null) { + if ((drawMiniIcon || circleCrossfadeColorKey != null) && miniDrawCanvas != null) { overlayImageView.draw(miniDrawCanvas); miniDrawCanvas.drawCircle(centerX, centerY, circleRadius, overlayPaint); } else { @@ -390,7 +418,7 @@ public class RadialProgress2 { } mediaActionDrawable.setBounds(centerX - circleRadius, centerY - circleRadius, centerX + circleRadius, centerY + circleRadius); mediaActionDrawable.setHasOverlayImage(overlayImageView.hasBitmapImage()); - if (drawMiniIcon) { + if ((drawMiniIcon || circleCrossfadeColorKey != null)) { if (miniDrawCanvas != null) { mediaActionDrawable.draw(miniDrawCanvas); } else { @@ -400,8 +428,11 @@ public class RadialProgress2 { mediaActionDrawable.setOverrideAlpha(overrideAlpha); mediaActionDrawable.draw(canvas); } + if (restore != Integer.MIN_VALUE && miniDrawCanvas != null) { + miniDrawCanvas.restoreToCount(restore); + } - if (drawMiniIcon) { + if ((drawMiniIcon || circleCrossfadeColorKey != null)) { int offset; int size; float cx; @@ -419,13 +450,18 @@ public class RadialProgress2 { } int halfSize = size / 2; - float alpha = miniMediaActionDrawable.getCurrentIcon() != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - miniMediaActionDrawable.getTransitionProgress(); - if (alpha == 0.0f) { - drawMiniIcon = false; + float alpha; + if (drawMiniIcon) { + alpha = miniMediaActionDrawable.getCurrentIcon() != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - miniMediaActionDrawable.getTransitionProgress(); + if (alpha == 0.0f) { + drawMiniIcon = false; + } + } else { + alpha = 1.0f; } if (miniDrawCanvas != null) { - miniDrawCanvas.drawCircle(AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(halfSize + 1) * alpha, Theme.checkboxSquare_eraserPaint); + miniDrawCanvas.drawCircle(AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(halfSize + 1) * alpha * miniIconScale, Theme.checkboxSquare_eraserPaint); } else { miniProgressBackgroundPaint.setColor(progressColor); canvas.drawCircle(cx, cy, AndroidUtilities.dp(12), miniProgressBackgroundPaint); @@ -435,9 +471,20 @@ public class RadialProgress2 { canvas.drawBitmap(miniDrawBitmap, (int) progressRect.left, (int) progressRect.top, null); } - canvas.drawCircle(cx, cy, AndroidUtilities.dp(halfSize) * alpha, circleMiniPaint); - miniMediaActionDrawable.setBounds((int) (cx - AndroidUtilities.dp(halfSize) * alpha), (int) (cy - AndroidUtilities.dp(halfSize) * alpha), (int) (cx + AndroidUtilities.dp(halfSize) * alpha), (int) (cy + AndroidUtilities.dp(halfSize) * alpha)); - miniMediaActionDrawable.draw(canvas); + restore = Integer.MIN_VALUE; + if (miniIconScale < 1.0f) { + restore = canvas.save(); + canvas.scale(miniIconScale, miniIconScale, cx, cy); + } + + canvas.drawCircle(cx, cy, AndroidUtilities.dp(halfSize) * alpha + AndroidUtilities.dp(1) * (1.0f - circleCheckProgress), circleMiniPaint); + if (drawMiniIcon) { + miniMediaActionDrawable.setBounds((int) (cx - AndroidUtilities.dp(halfSize) * alpha), (int) (cy - AndroidUtilities.dp(halfSize) * alpha), (int) (cx + AndroidUtilities.dp(halfSize) * alpha), (int) (cy + AndroidUtilities.dp(halfSize) * alpha)); + miniMediaActionDrawable.draw(canvas); + } + if (restore != Integer.MIN_VALUE) { + canvas.restoreToCount(restore); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java index d6ca6c812..ce747f96b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Paint; import android.graphics.RectF; import org.telegram.messenger.AndroidUtilities; @@ -23,10 +24,28 @@ public class RecordStatusDrawable extends StatusDrawable { private RectF rect = new RectF(); private float progress; + Paint currentPaint; + + public RecordStatusDrawable(boolean createPaint) { + if (createPaint) { + currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + currentPaint.setStyle(Paint.Style.STROKE); + currentPaint.setStrokeCap(Paint.Cap.ROUND); + currentPaint.setStrokeWidth(AndroidUtilities.dp(2)); + } + } + public void setIsChat(boolean value) { isChat = value; } + @Override + public void setColor(int color) { + if (currentPaint != null) { + currentPaint.setColor(color); + } + } + private void update() { long newTime = System.currentTimeMillis(); long dt = newTime - lastUpdateTime; @@ -53,19 +72,20 @@ public class RecordStatusDrawable extends StatusDrawable { @Override public void draw(Canvas canvas) { + Paint paint = currentPaint == null ? Theme.chat_statusRecordPaint : currentPaint; canvas.save(); canvas.translate(0, getIntrinsicHeight() / 2 + AndroidUtilities.dp(isChat ? 1 : 2)); for (int a = 0; a < 4; a++) { if (a == 0) { - Theme.chat_statusRecordPaint.setAlpha((int) (255 * progress)); + paint.setAlpha((int) (255 * progress)); } else if (a == 3) { - Theme.chat_statusRecordPaint.setAlpha((int) (255 * (1.0f - progress))); + paint.setAlpha((int) (255 * (1.0f - progress))); } else { - Theme.chat_statusRecordPaint.setAlpha(255); + paint.setAlpha(255); } float side = AndroidUtilities.dp(4) * a + AndroidUtilities.dp(4) * progress; rect.set(-side, -side, side, side); - canvas.drawArc(rect, -15, 30, false, Theme.chat_statusRecordPaint); + canvas.drawArc(rect, -15, 30, false, paint); } canvas.restore(); if (started) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java index 6b8a15e5e..4d133ff05 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java @@ -9,7 +9,6 @@ import android.view.View; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.ui.Cells.ChatMessageCell; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index cdb798dcc..50ddcf73a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -1884,4 +1884,12 @@ public class RecyclerListView extends RecyclerView { return false; } } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + if (fastScroll != null) { + fastScroll.setTranslationY(translationY); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RoundStatusDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RoundStatusDrawable.java index 84017d7c2..812472e56 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RoundStatusDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RoundStatusDrawable.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Paint; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -22,6 +23,21 @@ public class RoundStatusDrawable extends StatusDrawable { private float progress; private int progressDirection = 1; + private Paint currentPaint; + + public RoundStatusDrawable(boolean createPaint) { + if (createPaint) { + currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + } + + @Override + public void setColor(int color) { + if (currentPaint != null) { + currentPaint.setColor(color); + } + } + public void setIsChat(boolean value) { isChat = value; } @@ -56,8 +72,9 @@ public class RoundStatusDrawable extends StatusDrawable { @Override public void draw(Canvas canvas) { - Theme.chat_statusPaint.setAlpha(55 + (int) (200 * progress)); - canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(isChat ? 8 : 9), AndroidUtilities.dp(4), Theme.chat_statusPaint); + Paint paint = currentPaint == null ? Theme.chat_statusPaint : currentPaint; + paint.setAlpha(55 + (int) (200 * progress)); + canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(isChat ? 8 : 9), AndroidUtilities.dp(4), paint); if (started) { update(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java index 3f9549f75..3c89c4cd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java @@ -144,6 +144,7 @@ public class SearchField extends FrameLayout { }); searchEditText.setOnEditorActionListener((v, actionId, event) -> { if (event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + searchEditText.hideActionMode(); AndroidUtilities.hideKeyboard(searchEditText); } return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java index c09d6fa12..0670a25d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -2,6 +2,7 @@ package org.telegram.ui.Components; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; @@ -109,6 +110,10 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie int n = getChildCount(); loop: for (int i = 0; i < n; i++) { View v = getChildAt(i); + ViewHolder holder = searchListView.getChildViewHolder(v); + if (holder == null || holder.shouldIgnore()) { + continue; + } int position = searchlayoutManager.getPosition(v); for (int k = 0; k < currentAnimators.size(); k++) { if (currentAnimators.get(k).setup(v, position)) { @@ -155,7 +160,8 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie searchContainer.addView(searchListView); searchContainer.addView(noMediaFiltersSearchView); - FilteredSearchView.LoadingView loadingView = new FilteredSearchView.LoadingView(context); + FlickerLoadingView loadingView = new FlickerLoadingView(context); + loadingView.setViewType(1); emptyView = new StickerEmptyView(context, loadingView) { @Override public void setVisibility(int visibility) { @@ -663,9 +669,21 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie public void runResultsEnterAnimation() { Set hasSet = new HashSet<>(); int n = searchListView.getChildCount(); + View progressView = null; for (int i = 0; i < n; i++) { - hasSet.add(searchlayoutManager.getPosition(searchListView.getChildAt(i))); + View child = searchListView.getChildAt(i); + int childPosition = searchlayoutManager.getPosition(child); + if (child instanceof FlickerLoadingView) { + progressView = child; + } else { + hasSet.add(childPosition); + } } + final View finalProgressView = progressView; + if (progressView != null) { + searchListView.removeView(progressView); + } + searchListView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -685,6 +703,23 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie animator.valueAnimator.start(); } } + if (finalProgressView != null && finalProgressView.getParent() == null) { + searchListView.addView(finalProgressView); + RecyclerView.LayoutManager layoutManager = searchListView.getLayoutManager(); + if (layoutManager != null) { + layoutManager.ignoreView(finalProgressView); + Animator animator = ObjectAnimator.ofFloat(finalProgressView, ALPHA, finalProgressView.getAlpha(), 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finalProgressView.setAlpha(1f); + layoutManager.stopIgnoringView(finalProgressView); + searchListView.removeView(finalProgressView); + } + }); + animator.start(); + } + } return true; } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java index df83770ef..46161d9e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java @@ -21,6 +21,8 @@ import android.view.View; import android.view.ViewConfiguration; import android.widget.FrameLayout; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -43,6 +45,8 @@ public class SeekBarView extends FrameLayout { private long lastUpdateTime; private float currentRadius; private int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; + private float transitionProgress = 1f; + private int transitionThumbX; public interface SeekBarViewDelegate { void onSeekBarDrag(boolean stop, float progress); @@ -72,8 +76,7 @@ public class SeekBarView extends FrameLayout { currentRadius = AndroidUtilities.dp(6); if (Build.VERSION.SDK_INT >= 21) { - int color = Theme.getColor(Theme.key_player_progress); - hoverDrawable = Theme.createSelectorDrawable(Color.argb(40, Color.red(color), Color.green(color), Color.blue(color)), 1, AndroidUtilities.dp(16)); + hoverDrawable = Theme.createSelectorDrawable(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_player_progress), 40), 1, AndroidUtilities.dp(16)); hoverDrawable.setCallback(this); hoverDrawable.setVisible(true, false); } @@ -116,7 +119,7 @@ public class SeekBarView extends FrameLayout { innerPaint1.setColor(inner); outerPaint1.setColor(outer); if (hoverDrawable != null) { - Theme.setDrawableColor(hoverDrawable, Color.argb(40, Color.red(outer), Color.green(outer), Color.blue(outer))); + Theme.setSelectorDrawableColor(hoverDrawable, ColorUtils.setAlphaComponent(outer, 40), true); } } @@ -127,7 +130,7 @@ public class SeekBarView extends FrameLayout { public void setOuterColor(int color) { outerPaint1.setColor(color); if (hoverDrawable != null) { - Theme.setDrawableColor(hoverDrawable, Color.argb(40, Color.red(color), Color.green(color), Color.blue(color))); + Theme.setSelectorDrawableColor(hoverDrawable, ColorUtils.setAlphaComponent(color, 40), true); } } @@ -246,6 +249,10 @@ public class SeekBarView extends FrameLayout { } public void setProgress(float progress) { + setProgress(progress, false); + } + + public void setProgress(float progress, boolean animated) { if (getMeasuredWidth() == 0) { progressToSet = progress; return; @@ -253,6 +260,10 @@ public class SeekBarView extends FrameLayout { progressToSet = -1; int newThumbX = (int) Math.ceil((getMeasuredWidth() - selectorWidth) * progress); if (thumbX != newThumbX) { + if (animated) { + transitionThumbX = thumbX; + transitionProgress = 0f; + } thumbX = newThumbX; if (thumbX < 0) { thumbX = 0; @@ -302,13 +313,14 @@ public class SeekBarView extends FrameLayout { hoverDrawable.setBounds(dx, dy, dx + AndroidUtilities.dp(32), dy + AndroidUtilities.dp(32)); hoverDrawable.draw(canvas); } + boolean needInvalidate = false; int newRad = AndroidUtilities.dp(pressed ? 8 : 6); + long newUpdateTime = SystemClock.elapsedRealtime(); + long dt = newUpdateTime - lastUpdateTime; + if (dt > 18) { + dt = 16; + } if (currentRadius != newRad) { - long newUpdateTime = SystemClock.elapsedRealtime(); - long dt = newUpdateTime - lastUpdateTime; - if (dt > 18) { - dt = 16; - } if (currentRadius < newRad) { currentRadius += AndroidUtilities.dp(1) * (dt / 60.0f); if (currentRadius > newRad) { @@ -320,9 +332,29 @@ public class SeekBarView extends FrameLayout { currentRadius = newRad; } } - invalidate(); + needInvalidate = true; + } + if (transitionProgress < 1f) { + transitionProgress += dt / 225f; + if (transitionProgress < 1f) { + needInvalidate = true; + } else { + transitionProgress = 1f; + } + } + if (transitionProgress < 1f) { + final float oldCircleProgress = 1f - Easings.easeInQuad.getInterpolation(Math.min(1f, transitionProgress * 3f)); + final float newCircleProgress = Easings.easeOutQuad.getInterpolation(transitionProgress); + if (oldCircleProgress > 0f) { + canvas.drawCircle(transitionThumbX + selectorWidth / 2, y + thumbSize / 2, currentRadius * oldCircleProgress, outerPaint1); + } + canvas.drawCircle(thumbX + selectorWidth / 2, y + thumbSize / 2, currentRadius * newCircleProgress, outerPaint1); + } else { + canvas.drawCircle(thumbX + selectorWidth / 2, y + thumbSize / 2, currentRadius, outerPaint1); + } + if (needInvalidate) { + postInvalidateOnAnimation(); } - canvas.drawCircle(thumbX + selectorWidth / 2, y + thumbSize / 2, currentRadius, outerPaint1); } public SeekBarAccessibilityDelegate getSeekBarAccessibilityDelegate() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java index a611e7cc3..b9908caec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Paint; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -21,6 +22,24 @@ public class SendingFileDrawable extends StatusDrawable { private boolean started = false; private float progress; + Paint currentPaint; + + public SendingFileDrawable(boolean createPaint) { + if (createPaint) { + currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + currentPaint.setStyle(Paint.Style.STROKE); + currentPaint.setStrokeCap(Paint.Cap.ROUND); + currentPaint.setStrokeWidth(AndroidUtilities.dp(2)); + } + } + + @Override + public void setColor(int color) { + if (currentPaint != null) { + currentPaint.setColor(color); + } + } + public void setIsChat(boolean value) { isChat = value; } @@ -51,17 +70,18 @@ public class SendingFileDrawable extends StatusDrawable { @Override public void draw(Canvas canvas) { + Paint paint = currentPaint == null ? Theme.chat_statusRecordPaint : currentPaint; for (int a = 0; a < 3; a++) { if (a == 0) { - Theme.chat_statusRecordPaint.setAlpha((int) (255 * progress)); + paint.setAlpha((int) (255 * progress)); } else if (a == 2) { - Theme.chat_statusRecordPaint.setAlpha((int) (255 * (1.0f - progress))); + paint.setAlpha((int) (255 * (1.0f - progress))); } else { - Theme.chat_statusRecordPaint.setAlpha(255); + paint.setAlpha(255); } float side = AndroidUtilities.dp(5) * a + AndroidUtilities.dp(5) * progress; - canvas.drawLine(side, AndroidUtilities.dp(isChat ? 3 : 4), side + AndroidUtilities.dp(4), AndroidUtilities.dp(isChat ? 7 : 8), Theme.chat_statusRecordPaint); - canvas.drawLine(side, AndroidUtilities.dp(isChat ? 11 : 12), side + AndroidUtilities.dp(4), AndroidUtilities.dp(isChat ? 7 : 8), Theme.chat_statusRecordPaint); + canvas.drawLine(side, AndroidUtilities.dp(isChat ? 3 : 4), side + AndroidUtilities.dp(4), AndroidUtilities.dp(isChat ? 7 : 8), paint); + canvas.drawLine(side, AndroidUtilities.dp(isChat ? 11 : 12), side + AndroidUtilities.dp(4), AndroidUtilities.dp(isChat ? 7 : 8), paint); } if (started) { 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 1cc4bb33d..8e614a170 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -75,7 +75,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.DialogsActivity; -import org.telegram.ui.ForwardsActivity; +import org.telegram.ui.MessageStatisticActivity; import java.util.ArrayList; import java.util.Collections; @@ -603,9 +603,16 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY - AndroidUtilities.dp(30)) { - dismiss(); - return true; + if (!fullHeight) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getY() < topOffset - AndroidUtilities.dp(30)) { + dismiss(); + return true; + } + } else { + if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY - AndroidUtilities.dp(30)) { + dismiss(); + return true; + } } return super.onInterceptTouchEvent(ev); } @@ -852,7 +859,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi }); containerView.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - if (BuildVars.DEBUG_PRIVATE_VERSION && parentFragment != null && ChatObject.hasAdminRights(parentFragment.getCurrentChat()) && sendingMessageObjects.size() > 0 && sendingMessageObjects.get(0).messageOwner.forwards > 0) { + if (parentFragment != null && ChatObject.hasAdminRights(parentFragment.getCurrentChat()) && sendingMessageObjects.size() > 0 && sendingMessageObjects.get(0).messageOwner.forwards > 0) { MessageObject messageObject = sendingMessageObjects.get(0); if (!messageObject.isForwarded()) { sharesCountLayout = new LinearLayout(context); @@ -860,7 +867,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sharesCountLayout.setGravity(Gravity.CENTER_VERTICAL); sharesCountLayout.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 2)); containerView.addView(sharesCountLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48, Gravity.RIGHT | Gravity.BOTTOM, 6, 0, -6, 0)); - sharesCountLayout.setOnClickListener(view -> parentFragment.presentFragment(new ForwardsActivity(messageObject))); + sharesCountLayout.setOnClickListener(view -> parentFragment.presentFragment(new MessageStatisticActivity(messageObject))); ImageView imageView = new ImageView(context); imageView.setImageResource(R.drawable.share_arrow); 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 85ce27a1d..67e5bd900 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -36,6 +36,10 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; @@ -62,7 +66,6 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Adapters.SearchAdapterHelper; import org.telegram.ui.ArticleViewer; import org.telegram.ui.Cells.ChatActionCell; @@ -79,7 +82,6 @@ import org.telegram.ui.Cells.SharedPhotoVideoCell; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.DialogsActivity; -import org.telegram.ui.FilteredSearchView; import org.telegram.ui.PhotoViewer; import org.telegram.ui.ProfileActivity; @@ -87,16 +89,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - @SuppressWarnings("unchecked") public class SharedMediaLayout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private static class MediaPage extends FrameLayout { private RecyclerListView listView; - private FilteredSearchView.LoadingView progressView; + private FlickerLoadingView progressView; private TextView emptyTextView; private ExtendedGridLayoutManager layoutManager; private ImageView emptyImageView; @@ -505,7 +503,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else if (view instanceof ContextLinkCell) { ContextLinkCell cell = (ContextLinkCell) view; MessageObject message = (MessageObject) cell.getParentObject(); - if (message != null && messageObject != null && message.getId() == messageObject.getId()) { + if (message != null && message.getId() == messageObject.getId()) { imageReceiver = cell.getPhotoImage(); cell.getLocationInWindow(coords); } @@ -1209,7 +1207,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[a].emptyTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), AndroidUtilities.dp(128)); mediaPages[a].emptyView.addView(mediaPages[a].emptyTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 24, 0, 0)); - mediaPages[a].progressView = new FilteredSearchView.LoadingView(context) { + mediaPages[a].progressView = new FlickerLoadingView(context) { @Override public int getColumnsCount() { @@ -1217,7 +1215,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } @Override - public int getType() { + public int getViewType() { if (mediaPage.selectedType == 0 || mediaPage.selectedType == 5) { return 2; } else if (mediaPage.selectedType == 1) { @@ -1227,7 +1225,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else if (mediaPage.selectedType == 3) { return 5; } - return super.getType(); + return 1; } @Override @@ -1237,6 +1235,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter super.onDraw(canvas); } }; + mediaPages[a].progressView.showDate(false); mediaPages[a].progressView.setVisibility(View.GONE); mediaPages[a].addView(mediaPages[a].progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (a != 0) { @@ -1253,7 +1252,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter floatingDateView.setTranslationY(-AndroidUtilities.dp(48)); addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 48 + 4, 0, 0)); - addView(fragmentContextView = new FragmentContextView(context, parent, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + addView(fragmentContextView = new FragmentContextView(context, parent, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); fragmentContextView.setSupportsCalls(false); fragmentContextView.setDelegate((start, show) -> { if (show && !start) { @@ -1589,7 +1588,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (lower_part != 0) { if (lower_part > 0) { args1.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { args1.putInt("chat_id", -lower_part); } } else { @@ -1619,7 +1618,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (lower_part != 0) { if (lower_part > 0) { args.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { TLRPC.Chat chat = profileActivity.getMessagesController().getChat(-lower_part); if (chat != null && chat.migrated_to != null) { args.putInt("migrated_to", lower_part); @@ -2051,8 +2050,21 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else if (newItemCount < oldItemCount) { adapter.notifyItemRangeRemoved(newItemCount, (oldItemCount - newItemCount)); } - if (listView != null && oldItemCount == 0 && newItemCount > 0) { + if (listView != null && newItemCount > oldItemCount) { RecyclerListView finalListView = listView; + int n = finalListView.getChildCount(); + AnimatorSet animatorSet = new AnimatorSet(); + View progressView = null; + for (int i = 0; i < n; i++) { + View child = finalListView.getChildAt(i); + if (child instanceof FlickerLoadingView) { + progressView = child; + } + } + final View finalProgressView = progressView; + if (progressView != null) { + finalListView.removeView(progressView); + } getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -2061,14 +2073,34 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter AnimatorSet animatorSet = new AnimatorSet(); for (int i = 0; i < n; i++) { View child = finalListView.getChildAt(i); - child.setAlpha(0); - int s = Math.min(finalListView.getMeasuredHeight(), Math.max(0, child.getTop())); - int delay = (int) ((s / (float) finalListView.getMeasuredHeight()) * 100); - ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f); - a.setStartDelay(delay); - a.setDuration(200); - animatorSet.playTogether(a); + if (finalListView.getChildAdapterPosition(child) >= oldItemCount - 1) { + child.setAlpha(0); + int s = Math.min(finalListView.getMeasuredHeight(), Math.max(0, child.getTop())); + int delay = (int) ((s / (float) finalListView.getMeasuredHeight()) * 100); + ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f); + a.setStartDelay(delay); + a.setDuration(200); + animatorSet.playTogether(a); + } + if (finalProgressView != null && finalProgressView.getParent() == null) { + finalListView.addView(finalProgressView); + RecyclerView.LayoutManager layoutManager = finalListView.getLayoutManager(); + if (layoutManager != null) { + layoutManager.ignoreView(finalProgressView); + Animator animator = ObjectAnimator.ofFloat(finalProgressView, ALPHA, finalProgressView.getAlpha(), 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finalProgressView.setAlpha(1f); + layoutManager.stopIgnoringView(finalProgressView); + finalListView.removeView(finalProgressView); + } + }); + animator.start(); + } + } } + animatorSet.start(); return true; } @@ -2269,7 +2301,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } } - } else if (id == NotificationCenter.messagePlayingDidStart) { + } else { MessageObject messageObject = (MessageObject) args[0]; if (messageObject.eventId != 0) { return; @@ -3072,7 +3104,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter break; case 2: default: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.showDate(false); + flickerLoadingView.setViewType(FlickerLoadingView.LINKS_TYPE); + view = flickerLoadingView; break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -3193,7 +3229,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter view = new SharedDocumentCell(mContext); break; case 2: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + view = flickerLoadingView; + if (currentType == MediaDataController.MEDIA_MUSIC) { + flickerLoadingView.setViewType(FlickerLoadingView.AUDIO_TYPE); + } else { + flickerLoadingView.setViewType(FlickerLoadingView.FILES_TYPE); + } + flickerLoadingView.showDate(false); + flickerLoadingView.setIsSingleCell(true); break; case 3: default: @@ -3355,7 +3399,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter break; case 1: default: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(74)); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.setViewType(FlickerLoadingView.PHOTOS_TYPE); + view = flickerLoadingView; break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -3898,7 +3945,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter break; case 1: default: - view = new LoadingCell(mContext); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.showDate(false); + flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); + view = flickerLoadingView; break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -4067,45 +4118,43 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter ArrayList resultArrayNames = new ArrayList<>(); ArrayList resultArray2 = new ArrayList<>(); - if (participantsCopy != null) { - for (int a = 0, N = participantsCopy.size(); a < N; a++) { - int userId; - TLObject o = participantsCopy.get(a); - if (o instanceof TLRPC.ChatParticipant) { - userId = ((TLRPC.ChatParticipant) o).user_id; - } else if (o instanceof TLRPC.ChannelParticipant) { - userId = ((TLRPC.ChannelParticipant) o).user_id; - } else { - continue; - } - TLRPC.User user = profileActivity.getMessagesController().getUser(userId); - if (user.id == profileActivity.getUserConfig().getClientUserId()) { - continue; + for (int a = 0, N = participantsCopy.size(); a < N; a++) { + int userId; + TLObject o = participantsCopy.get(a); + if (o instanceof TLRPC.ChatParticipant) { + userId = ((TLRPC.ChatParticipant) o).user_id; + } else if (o instanceof TLRPC.ChannelParticipant) { + userId = ((TLRPC.ChannelParticipant) o).user_id; + } else { + continue; + } + TLRPC.User user = profileActivity.getMessagesController().getUser(userId); + if (user.id == profileActivity.getUserConfig().getClientUserId()) { + continue; + } + + String name = UserObject.getUserName(user).toLowerCase(); + String tName = LocaleController.getInstance().getTranslitString(name); + if (name.equals(tName)) { + tName = null; + } + + int found = 0; + for (String q : search) { + if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { + found = 1; + } else if (user.username != null && user.username.startsWith(q)) { + found = 2; } - String name = UserObject.getUserName(user).toLowerCase(); - String tName = LocaleController.getInstance().getTranslitString(name); - if (name.equals(tName)) { - tName = null; - } - - int found = 0; - for (String q : search) { - if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { - found = 1; - } else if (user.username != null && user.username.startsWith(q)) { - found = 2; - } - - if (found != 0) { - if (found == 1) { - resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q)); - } else { - resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q)); - } - resultArray2.add(o); - break; + if (found != 0) { + if (found == 1) { + resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q)); + } else { + resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q)); } + resultArray2.add(o); + break; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java new file mode 100644 index 000000000..482f3e4b0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java @@ -0,0 +1,432 @@ +package org.telegram.ui.Components; + +import android.graphics.Bitmap; +import android.text.TextUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DownloadController; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Cells.ChatMessageCell; + +import java.io.File; + +public class SlotsDrawable extends RLottieDrawable { + + enum ReelValue { + bar, + berries, + lemon, + seven, + sevenWin + } + + private ReelValue left; + private ReelValue center; + private ReelValue right; + + private long[] nativePtrs = new long[5]; + private int[] frameCounts = new int[5]; + private int[] frameNums = new int[5]; + private long[] secondNativePtrs = new long[3]; + private int[] secondFrameCounts = new int[3]; + private int[] secondFrameNums = new int[3]; + + public SlotsDrawable(String diceEmoji, int w, int h) { + super(diceEmoji, w, h); + + loadFrameRunnable = () -> { + if (isRecycled) { + return; + } + if (nativePtr == 0 || isDice == 2 && secondNativePtr == 0) { + if (frameWaitSync != null) { + frameWaitSync.countDown(); + } + uiHandler.post(uiRunnableNoFrame); + return; + } + if (backgroundBitmap == null) { + try { + backgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + } catch (Throwable e) { + FileLog.e(e); + } + } + if (backgroundBitmap != null) { + try { + int result; + if (isDice == 1) { + result = -1; + for (int a = 0; a < nativePtrs.length; a++) { + result = getFrame(nativePtrs[a], frameNums[a], backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), a == 0); + if (a == 0) { + continue; + } + if (frameNums[a] + 1 < frameCounts[a]) { + frameNums[a]++; + } else if (a != 4) { + frameNums[a] = 0; + nextFrameIsLast = false; + if (secondNativePtr != 0) { + isDice = 2; + } + } + } + } else { + if (setLastFrame) { + for (int a = 0; a < secondFrameNums.length; a++) { + secondFrameNums[a] = secondFrameCounts[a] - 1; + } + } + if (autoRepeatPlayCount == 1) { + if (frameNums[0] + 1 < frameCounts[0]) { + frameNums[0]++; + } else { + frameNums[0] = -1; + } + } + getFrame(nativePtrs[0], Math.max(frameNums[0], 0), backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), true); + for (int a = 0; a < secondNativePtrs.length; a++) { + getFrame(secondNativePtrs[a], secondFrameNums[a] >= 0 ? secondFrameNums[a] : (secondFrameCounts[a] - 1), backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), false); + if (secondFrameNums[a] + 1 < secondFrameCounts[a]) { + secondFrameNums[a]++; + } else { + secondFrameNums[a] = -1; + } + } + result = getFrame(nativePtrs[4], frameNums[4], backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), false); + if (frameNums[4] + 1 < frameCounts[4]) { + frameNums[4]++; + } + if (secondFrameNums[0] == -1 && secondFrameNums[1] == -1 && secondFrameNums[2] == -1) { + nextFrameIsLast = true; + } + if (left == right && right == center) { + if (secondFrameNums[0] == secondFrameCounts[0] - 100) { + if (autoRepeatPlayCount == 0) { + autoRepeatPlayCount++; + } + if (left == ReelValue.sevenWin) { + Runnable runnable = onFinishCallback.get(); + if (runnable != null) { + AndroidUtilities.runOnUIThread(runnable); + } + } + } + } else { + frameNums[0] = -1; + } + } + if (result == -1) { + uiHandler.post(uiRunnableNoFrame); + if (frameWaitSync != null) { + frameWaitSync.countDown(); + } + return; + } + nextRenderingBitmap = backgroundBitmap; + } catch (Exception e) { + FileLog.e(e); + } + } + uiHandler.post(uiRunnable); + if (frameWaitSync != null) { + frameWaitSync.countDown(); + } + }; + } + + private ReelValue reelValue(int rawValue) { + switch (rawValue) { + case 0: + return ReelValue.bar; + case 1: + return ReelValue.berries; + case 2: + return ReelValue.lemon; + case 3: + default: + return ReelValue.seven; + } + } + + private void init(int rawValue) { + rawValue--; + + int leftRawValue = rawValue & 3; + int centerRawValue = rawValue >> 2 & 3; + int rightRawValue = rawValue >> 4; + + ReelValue leftReelValue = reelValue(leftRawValue); + ReelValue centerReelValue = reelValue(centerRawValue); + ReelValue rightReelValue = reelValue(rightRawValue); + + if (leftReelValue == ReelValue.seven && centerReelValue == ReelValue.seven && rightReelValue == ReelValue.seven) { + leftReelValue = ReelValue.sevenWin; + centerReelValue = ReelValue.sevenWin; + rightReelValue = ReelValue.sevenWin; + } + + left = leftReelValue; + center = centerReelValue; + right = rightReelValue; + } + + private boolean is777() { + return left == ReelValue.sevenWin && center == ReelValue.sevenWin && right == ReelValue.sevenWin; + } + + public boolean setBaseDice(ChatMessageCell messageCell, TLRPC.TL_messages_stickerSet stickerSet) { + if (nativePtr != 0 || loadingInBackground) { + return true; + } + loadingInBackground = true; + MessageObject currentMessageObject = messageCell.getMessageObject(); + int account = messageCell.getMessageObject().currentAccount; + Utilities.globalQueue.postRunnable(() -> { + if (destroyAfterLoading) { + AndroidUtilities.runOnUIThread(() -> { + loadingInBackground = false; + if (!secondLoadingInBackground && destroyAfterLoading) { + recycle(); + } + }); + return; + } + boolean loading = false; + for (int a = 0; a < nativePtrs.length; a++) { + if (nativePtrs[a] != 0) { + continue; + } + int num; + if (a == 0) { + num = 1; + } else if (a == 1) { + num = 8; + } else if (a == 2) { + num = 14; + } else if (a == 3) { + num = 20; + } else { + num = 2; + } + TLRPC.Document document = stickerSet.documents.get(num); + File path = FileLoader.getPathToAttach(document, true); + String json = readRes(path, 0); + if (TextUtils.isEmpty(json)) { + loading = true; + AndroidUtilities.runOnUIThread(() -> { + String fileName = FileLoader.getAttachFileName(document); + DownloadController.getInstance(account).addLoadingFileObserver(fileName, currentMessageObject, messageCell); + FileLoader.getInstance(account).loadFile(document, stickerSet, 1, 1); + }); + } else { + nativePtrs[a] = createWithJson(json, "dice", metaData, null); + frameCounts[a] = metaData[0]; + } + } + if (loading) { + AndroidUtilities.runOnUIThread(() -> loadingInBackground = false); + return; + } + AndroidUtilities.runOnUIThread(() -> { + loadingInBackground = false; + if (!secondLoadingInBackground && destroyAfterLoading) { + recycle(); + return; + } + nativePtr = nativePtrs[0]; + DownloadController.getInstance(account).removeLoadingFileObserver(messageCell); + timeBetweenFrames = Math.max(16, (int) (1000.0f / metaData[1])); + scheduleNextGetFrame(); + invalidateInternal(); + }); + }); + + return true; + } + + public boolean setDiceNumber(ChatMessageCell messageCell, int number, TLRPC.TL_messages_stickerSet stickerSet, boolean instant) { + if (secondNativePtr != 0 || secondLoadingInBackground) { + return true; + } + init(number); + MessageObject currentMessageObject = messageCell.getMessageObject(); + int account = messageCell.getMessageObject().currentAccount; + + secondLoadingInBackground = true; + Utilities.globalQueue.postRunnable(() -> { + if (destroyAfterLoading) { + AndroidUtilities.runOnUIThread(() -> { + secondLoadingInBackground = false; + if (!loadingInBackground && destroyAfterLoading) { + recycle(); + } + }); + return; + } + + boolean loading = false; + for (int a = 0; a < secondNativePtrs.length + 2; a++) { + int num; + if (a <= 2) { + if (secondNativePtrs[a] != 0) { + continue; + } + if (a == 0) { + if (left == ReelValue.bar) { + num = 5; + } else if (left == ReelValue.berries) { + num = 6; + } else if (left == ReelValue.lemon) { + num = 7; + } else if (left == ReelValue.seven) { + num = 4; + } else { + num = 3; + } + } else if (a == 1) { + if (center == ReelValue.bar) { + num = 11; + } else if (center == ReelValue.berries) { + num = 12; + } else if (center == ReelValue.lemon) { + num = 13; + } else if (center == ReelValue.seven) { + num = 10; + } else { + num = 9; + } + } else { + if (right == ReelValue.bar) { + num = 17; + } else if (right == ReelValue.berries) { + num = 18; + } else if (right == ReelValue.lemon) { + num = 19; + } else if (right == ReelValue.seven) { + num = 16; + } else { + num = 15; + } + } + } else { + if (nativePtrs[a] != 0) { + continue; + } + if (a == 3) { + num = 1; + } else { + num = 2; + } + } + TLRPC.Document document = stickerSet.documents.get(num); + File path = FileLoader.getPathToAttach(document, true); + String json = readRes(path, 0); + if (TextUtils.isEmpty(json)) { + loading = true; + AndroidUtilities.runOnUIThread(() -> { + String fileName = FileLoader.getAttachFileName(document); + DownloadController.getInstance(account).addLoadingFileObserver(fileName, currentMessageObject, messageCell); + FileLoader.getInstance(account).loadFile(document, stickerSet, 1, 1); + }); + } else { + if (a <= 2) { + secondNativePtrs[a] = createWithJson(json, "dice", metaData, null); + secondFrameCounts[a] = metaData[0]; + } else { + nativePtrs[a == 3 ? 0 : 4] = createWithJson(json, "dice", metaData, null); + frameCounts[a == 3 ? 0 : 4] = metaData[0]; + } + } + } + if (loading) { + AndroidUtilities.runOnUIThread(() -> secondLoadingInBackground = false); + return; + } + AndroidUtilities.runOnUIThread(() -> { + if (instant && nextRenderingBitmap == null && renderingBitmap == null && loadFrameTask == null) { + isDice = 2; + setLastFrame = true; + } + secondLoadingInBackground = false; + if (!loadingInBackground && destroyAfterLoading) { + recycle(); + return; + } + secondNativePtr = secondNativePtrs[0]; + DownloadController.getInstance(account).removeLoadingFileObserver(messageCell); + timeBetweenFrames = Math.max(16, (int) (1000.0f / metaData[1])); + scheduleNextGetFrame(); + invalidateInternal(); + }); + }); + return true; + } + + @Override + public void recycle() { + isRunning = false; + isRecycled = true; + checkRunningTasks(); + if (loadingInBackground || secondLoadingInBackground) { + destroyAfterLoading = true; + } else if (loadFrameTask == null && cacheGenerateTask == null) { + for (int a = 0; a < nativePtrs.length; a++) { + if (nativePtrs[a] != 0) { + if (nativePtrs[a] == nativePtr) { + nativePtr = 0; + } + destroy(nativePtrs[a]); + nativePtrs[a] = 0; + } + } + for (int a = 0; a < secondNativePtrs.length; a++) { + if (secondNativePtrs[a] != 0) { + if (secondNativePtrs[a] == secondNativePtr) { + secondNativePtr = 0; + } + destroy(secondNativePtrs[a]); + secondNativePtrs[a] = 0; + } + } + recycleResources(); + } else { + destroyWhenDone = true; + } + } + + @Override + protected void decodeFrameFinishedInternal() { + if (destroyWhenDone) { + checkRunningTasks(); + if (loadFrameTask == null && cacheGenerateTask == null) { + for (int a = 0; a < nativePtrs.length; a++) { + if (nativePtrs[a] != 0) { + destroy(nativePtrs[a]); + nativePtrs[a] = 0; + } + } + for (int a = 0; a < secondNativePtrs.length; a++) { + if (secondNativePtrs[a] != 0) { + destroy(secondNativePtrs[a]); + secondNativePtrs[a] = 0; + } + } + } + } + if (nativePtr == 0 && secondNativePtr == 0) { + recycleResources(); + return; + } + waitingForNextTask = true; + if (!hasParentView()) { + stop(); + } + scheduleNextGetFrame(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StatusDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StatusDrawable.java index e3bf3ae77..3381e69f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StatusDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StatusDrawable.java @@ -8,10 +8,12 @@ package org.telegram.ui.Components; +import android.graphics.Paint; import android.graphics.drawable.Drawable; public abstract class StatusDrawable extends Drawable { public abstract void start(); public abstract void stop(); public abstract void setIsChat(boolean value); + public abstract void setColor(int color); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SvgHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SvgHelper.java index 15401aea1..4f8a4964d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SvgHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SvgHelper.java @@ -25,10 +25,14 @@ package org.telegram.ui.Components; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import org.telegram.messenger.FileLog; import org.xml.sax.Attributes; @@ -47,12 +51,109 @@ import javax.xml.parsers.SAXParserFactory; public class SvgHelper { + private static class Line { + float x1, y1, x2, y2; + + public Line(float x1, float y1, float x2, float y2) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + } + + private static class Circle { + float x1, y1, rad; + + public Circle(float x1, float y1, float rad) { + this.x1 = x1; + this.y1 = y1; + this.rad = rad; + } + } + + private static class Oval { + RectF rect; + + public Oval(RectF rect) { + this.rect = rect; + } + } + + public static class SvgDrawable extends Drawable { + + private ArrayList commands = new ArrayList<>(); + private HashMap paints = new HashMap<>(); + private int width; + private int height; + + @Override + public void draw(Canvas canvas) { + Rect bounds = getBounds(); + float scaleX = bounds.width() / (float) width; + float scaleY = bounds.height() / (float) height; + float scale = Math.max(scaleX, scaleY); + canvas.scale(scale, scale); + for (int a = 0, N = commands.size(); a < N; a++) { + Object object = commands.get(a); + if (object instanceof Matrix) { + canvas.save(); + canvas.concat((Matrix) object); + } else if (object == null) { + canvas.restore(); + } else { + Paint paint = paints.get(object); + if (object instanceof Path) { + canvas.drawPath((Path) object, paint); + } else if (object instanceof Rect) { + canvas.drawRect((Rect) object, paint); + } else if (object instanceof RectF) { + canvas.drawRect((RectF) object, paint); + } else if (object instanceof Line) { + Line line = (Line) object; + canvas.drawLine(line.x1, line.y1, line.x2, line.y2, paint); + } else if (object instanceof Circle) { + Circle circle = (Circle) object; + canvas.drawCircle(circle.x1, circle.y1, circle.rad, paint); + } else if (object instanceof Oval) { + Oval oval = (Oval) object; + canvas.drawOval(oval.rect, paint); + } + } + } + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + private void addCommand(Object command, Paint paint) { + commands.add(command); + paints.put(command, new Paint(paint)); + } + + private void addCommand(Object command) { + commands.add(command); + } + } + public static Bitmap getBitmap(File file, int width, int height, boolean white) { try (FileInputStream stream = new FileInputStream(file)) { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); - SVGHandler handler = new SVGHandler(width, height, white); + SVGHandler handler = new SVGHandler(width, height, white, false); xr.setContentHandler(handler); xr.parse(new InputSource(stream)); return handler.getBitmap(); @@ -67,7 +168,7 @@ public class SvgHelper { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); - SVGHandler handler = new SVGHandler(width, height, white); + SVGHandler handler = new SVGHandler(width, height, white, false); xr.setContentHandler(handler); xr.parse(new InputSource(new StringReader(xml))); return handler.getBitmap(); @@ -77,6 +178,21 @@ public class SvgHelper { } } + public static SvgDrawable getDrawable(String xml) { + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser sp = spf.newSAXParser(); + XMLReader xr = sp.getXMLReader(); + SVGHandler handler = new SVGHandler(0, 0, false, true); + xr.setContentHandler(handler); + xr.parse(new InputSource(new StringReader(xml))); + return handler.getDrawable(); + } catch (Exception e) { + FileLog.e(e); + return null; + } + } + public static Bitmap getBitmapByPathOnly(String pathString, int svgWidth, int svgHeight, int width, int height) { try { Path path = doPath(pathString); @@ -632,6 +748,7 @@ public class SvgHelper { private Canvas canvas; private Bitmap bitmap; + private SvgDrawable drawable; private int desiredWidth; private int desiredHeight; private float scale = 1.0f; @@ -643,10 +760,13 @@ public class SvgHelper { private HashMap globalStyles = new HashMap<>(); - private SVGHandler(int dw, int dh, boolean white) { + private SVGHandler(int dw, int dh, boolean white, boolean asDrawable) { desiredWidth = dw; desiredHeight = dh; whiteOnly = white; + if (asDrawable) { + drawable = new SvgDrawable(); + } } @Override @@ -678,7 +798,7 @@ public class SvgHelper { if (whiteOnly) { paint.setColor(0xffffffff); } else { - paint.setColor(0xFF000000); + paint.setColor(0xff000000); } return true; } @@ -746,14 +866,22 @@ public class SvgHelper { pushed = transform != null; if (pushed) { final Matrix matrix = parseTransform(transform); - canvas.save(); - canvas.concat(matrix); + if (drawable != null) { + drawable.addCommand(matrix); + } else { + canvas.save(); + canvas.concat(matrix); + } } } private void popTransform() { if (pushed) { - canvas.restore(); + if (drawable != null) { + drawable.addCommand(null); + } else { + canvas.restore(); + } } } @@ -783,16 +911,21 @@ public class SvgHelper { if (width == 0 || height == 0) { width = desiredWidth; height = desiredHeight; - } else { + } else if (desiredWidth != 0 && desiredHeight != 0) { scale = Math.min(desiredWidth / (float) width, desiredHeight / (float) height); width *= scale; height *= scale; } - bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.eraseColor(0); - canvas = new Canvas(bitmap); - if (scale != 0) { - canvas.scale(scale, scale); + if (drawable == null) { + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.eraseColor(0); + canvas = new Canvas(bitmap); + if (scale != 0) { + canvas.scale(scale, scale); + } + } else { + drawable.width = width; + drawable.height = height; } break; } @@ -822,10 +955,18 @@ public class SvgHelper { pushTransform(atts); Properties props = new Properties(atts, globalStyles); if (doFill(props)) { - canvas.drawRect(x, y, x + width, y + height, paint); + if (drawable != null) { + drawable.addCommand(new RectF(x, y, x + width, y + height), paint); + } else { + canvas.drawRect(x, y, x + width, y + height, paint); + } } if (doStroke(props)) { - canvas.drawRect(x, y, x + width, y + height, paint); + if (drawable != null) { + drawable.addCommand(new RectF(x, y, x + width, y + height), paint); + } else { + canvas.drawRect(x, y, x + width, y + height, paint); + } } popTransform(); break; @@ -838,7 +979,11 @@ public class SvgHelper { Properties props = new Properties(atts, globalStyles); if (doStroke(props)) { pushTransform(atts); - canvas.drawLine(x1, y1, x2, y2, paint); + if (drawable != null) { + drawable.addCommand(new Line(x1, y1, x2, y2), paint); + } else { + canvas.drawLine(x1, y1, x2, y2, paint); + } popTransform(); } break; @@ -851,10 +996,18 @@ public class SvgHelper { pushTransform(atts); Properties props = new Properties(atts, globalStyles); if (doFill(props)) { - canvas.drawCircle(centerX, centerY, radius, paint); + if (drawable != null) { + drawable.addCommand(new Circle(centerX, centerY, radius), paint); + } else { + canvas.drawCircle(centerX, centerY, radius, paint); + } } if (doStroke(props)) { - canvas.drawCircle(centerX, centerY, radius, paint); + if (drawable != null) { + drawable.addCommand(new Circle(centerX, centerY, radius), paint); + } else { + canvas.drawCircle(centerX, centerY, radius, paint); + } } popTransform(); } @@ -870,10 +1023,18 @@ public class SvgHelper { Properties props = new Properties(atts, globalStyles); rect.set(centerX - radiusX, centerY - radiusY, centerX + radiusX, centerY + radiusY); if (doFill(props)) { - canvas.drawOval(rect, paint); + if (drawable != null) { + drawable.addCommand(new Oval(rect), paint); + } else { + canvas.drawOval(rect, paint); + } } if (doStroke(props)) { - canvas.drawOval(rect, paint); + if (drawable != null) { + drawable.addCommand(new Oval(rect), paint); + } else { + canvas.drawOval(rect, paint); + } } popTransform(); } @@ -898,10 +1059,18 @@ public class SvgHelper { p.close(); } if (doFill(props)) { - canvas.drawPath(p, paint); + if (drawable != null) { + drawable.addCommand(p, paint); + } else { + canvas.drawPath(p, paint); + } } if (doStroke(props)) { - canvas.drawPath(p, paint); + if (drawable != null) { + drawable.addCommand(p, paint); + } else { + canvas.drawPath(p, paint); + } } popTransform(); } @@ -912,10 +1081,18 @@ public class SvgHelper { pushTransform(atts); Properties props = new Properties(atts, globalStyles); if (doFill(props)) { - canvas.drawPath(p, paint); + if (drawable != null) { + drawable.addCommand(p, paint); + } else { + canvas.drawPath(p, paint); + } } if (doStroke(props)) { - canvas.drawPath(p, paint); + if (drawable != null) { + drawable.addCommand(p, paint); + } else { + canvas.drawPath(p, paint); + } } popTransform(); break; @@ -965,6 +1142,10 @@ public class SvgHelper { public Bitmap getBitmap() { return bitmap; } + + public SvgDrawable getDrawable() { + return drawable; + } } private static final double[] pow10 = new double[128]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersAlert.java index 3f303f55b..053f1127f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersAlert.java @@ -66,7 +66,9 @@ public class TrendingStickersAlert extends BottomSheet { } AndroidUtilities.hideKeyboard(view); } - updateLayout(); + if (dy != 0) { + updateLayout(); + } } }); } @@ -147,7 +149,6 @@ public class TrendingStickersAlert extends BottomSheet { TrendingStickersAlert.this.setAllowNestedScroll(false); gluedToTop = true; } - layout.setContentViewPaddingBottom(keyboardHeight); } } }); @@ -175,8 +176,13 @@ public class TrendingStickersAlert extends BottomSheet { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { final int statusBarHeight = Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0; - final int height = MeasureSpec.getSize(heightMeasureSpec) - statusBarHeight; + final int height = MeasureSpec.getSize(getMeasuredHeight()) - statusBarHeight; final int keyboardHeight = measureKeyboardHeight(); final int padding = (int) ((height + keyboardHeight) * 0.2f); @@ -187,22 +193,15 @@ public class TrendingStickersAlert extends BottomSheet { gluedToTop = true; } else { layout.glueToTop(false); - layout.setContentViewPaddingTop(padding); TrendingStickersAlert.this.setAllowNestedScroll(true); gluedToTop = false; } - layout.setContentViewPaddingBottom(keyboardHeight); + layout.setContentViewPaddingTop(padding); if (getPaddingTop() != statusBarHeight) { setPadding(backgroundPaddingLeft, statusBarHeight, backgroundPaddingLeft, 0); } ignoreLayout = false; - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - updateLayout(); + super.onLayout(changed, l, t, r, b); } @Override @@ -214,6 +213,7 @@ public class TrendingStickersAlert extends BottomSheet { @Override protected void onDraw(Canvas canvas) { + updateLayout(); super.onDraw(canvas); final float fraction = getFraction(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersLayout.java index 47244f3b5..0e473ee89 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TrendingStickersLayout.java @@ -138,10 +138,16 @@ public class TrendingStickersLayout extends FrameLayout implements NotificationC @Override public void setAdapterVisible(boolean visible) { + boolean changed = false; if (visible && listView.getAdapter() != searchAdapter) { listView.setAdapter(searchAdapter); + changed = true; } else if (!visible && listView.getAdapter() != adapter) { listView.setAdapter(adapter); + changed = true; + } + if (changed && listView.getAdapter().getItemCount() > 0) { + layoutManager.scrollToPositionWithOffset(0, -listView.getPaddingTop() + AndroidUtilities.dp(58) + topOffset, false); } } @@ -261,6 +267,22 @@ public class TrendingStickersLayout extends FrameLayout implements NotificationC if (glueToTopAnimator != null) { return 0; } + if (gluedToTop) { + int minPosition = 1; + for (int i = 0; i < getChildCount(); i++) { + int p = listView.getChildAdapterPosition(getChildAt(i)); + if (p < minPosition) { + minPosition = p; + break; + } + } + if (minPosition == 0) { + View minView = layoutManager.findViewByPosition(minPosition); + if (minView != null && minView.getTop() - dy > AndroidUtilities.dp(58)) { + dy = minView.getTop() - AndroidUtilities.dp(58); + } + } + } return super.scrollVerticallyBy(dy, recycler, state); } }); @@ -448,16 +470,7 @@ public class TrendingStickersLayout extends FrameLayout implements NotificationC paddingTop += AndroidUtilities.dp(58); if (listView.getPaddingTop() != paddingTop) { ignoreLayout = true; - listView.setPadding(0, paddingTop, 0, listView.getPaddingBottom()); - ignoreLayout = false; - } - } - - public void setContentViewPaddingBottom(int paddingBottom) { - if (listView.getPaddingBottom() != paddingBottom) { - ignoreLayout = true; - listView.setPadding(0, listView.getPaddingTop(), 0, paddingBottom); - updateLastItemInAdapter(); + listView.setPadding(0, paddingTop, 0, 0); ignoreLayout = false; } } @@ -481,6 +494,12 @@ public class TrendingStickersLayout extends FrameLayout implements NotificationC return true; } View child = listView.getChildAt(0); + for (int i = 1; i < listView.getChildCount(); i++) { + View view = listView.getChildAt(i); + if (view.getTop() < child.getTop()) { + child = view; + } + } RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child); int top = child.getTop() - AndroidUtilities.dp(58); int newOffset = top > 0 && holder != null && holder.getAdapterPosition() == 0 ? top : 0; @@ -546,7 +565,6 @@ public class TrendingStickersLayout extends FrameLayout implements NotificationC glueToTopAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - setContentViewPaddingTop(0); glueToTopAnimator = null; } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java index 2977e7547..89fef73bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Paint; import android.graphics.PixelFormat; import android.view.animation.DecelerateInterpolator; @@ -29,6 +30,21 @@ public class TypingDotsDrawable extends StatusDrawable { private boolean started = false; private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); + private Paint currentPaint; + + public TypingDotsDrawable(boolean createPaint) { + if (createPaint) { + currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + } + + @Override + public void setColor(int color) { + if (currentPaint != null) { + currentPaint.setColor(color); + } + } + public void setIsChat(boolean value) { isChat = value; } @@ -91,10 +107,17 @@ public class TypingDotsDrawable extends StatusDrawable { } else { y = AndroidUtilities.dp(9.3f) + getBounds().top; } - Theme.chat_statusPaint.setAlpha(255); - canvas.drawCircle(AndroidUtilities.dp(3), y, scales[0] * AndroidUtilities.density, Theme.chat_statusPaint); - canvas.drawCircle(AndroidUtilities.dp(9), y, scales[1] * AndroidUtilities.density, Theme.chat_statusPaint); - canvas.drawCircle(AndroidUtilities.dp(15), y, scales[2] * AndroidUtilities.density, Theme.chat_statusPaint); + Paint paint; + if (currentPaint == null) { + paint = Theme.chat_statusPaint; + paint.setAlpha(255); + } else { + paint = currentPaint; + } + + canvas.drawCircle(AndroidUtilities.dp(3), y, scales[0] * AndroidUtilities.density, paint); + canvas.drawCircle(AndroidUtilities.dp(9), y, scales[1] * AndroidUtilities.density, paint); + canvas.drawCircle(AndroidUtilities.dp(15), y, scales[2] * AndroidUtilities.density, paint); checkUpdate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java index 65692218a..0cbf97fdd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java @@ -128,11 +128,17 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid private boolean looping; private int repeatCount; + private boolean shouldPauseOther; + Handler audioUpdateHandler = new Handler(Looper.getMainLooper()); private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); public VideoPlayer() { + this(true); + } + + public VideoPlayer(boolean pauseOther) { mediaDataSourceFactory = new ExtendedDefaultDataSourceFactory(ApplicationLoader.applicationContext, BANDWIDTH_METER, new DefaultHttpDataSourceFactory("Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/47.0 (Chrome)", BANDWIDTH_METER)); mainHandler = new Handler(); @@ -141,7 +147,10 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); lastReportedPlaybackState = ExoPlayer.STATE_IDLE; - NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.playerDidStartPlaying); + shouldPauseOther = pauseOther; + if (pauseOther) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.playerDidStartPlaying); + } } @Override @@ -339,7 +348,9 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid audioPlayer.release(async); audioPlayer = null; } - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.playerDidStartPlaying); + if (shouldPauseOther) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.playerDidStartPlaying); + } } @Override @@ -572,7 +583,7 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { maybeReportPlayerState(); - if (playWhenReady && playbackState == Player.STATE_READY && !isMuted()) { + if (playWhenReady && playbackState == Player.STATE_READY && !isMuted() && shouldPauseOther) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.playerDidStartPlaying, this); } if (!videoPlayerReady && playbackState == Player.STATE_READY) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPToggleButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPToggleButton.java index 615cae93e..49b0cff47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPToggleButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPToggleButton.java @@ -6,7 +6,6 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -14,7 +13,6 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; import android.view.Gravity; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; @@ -290,7 +288,7 @@ public class VoIPToggleButton extends FrameLayout { textView[1].setVisibility(View.GONE); } - if (!iconChangeColor) { + if (!iconChangeColor && icon[1] != null) { icon[0] = icon[1]; icon[1] = null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 2072c4cd0..cd50329b6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -509,7 +509,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (inPreviewMode) { top = AndroidUtilities.statusBarHeight; } else { - top = inPreviewMode ? 0 : (int) (-getY() + actionBar.getY()); + top = (int) (-getY() + actionBar.getY()); } if (whiteActionBar) { if (searchAnimationProgress == 1f) { @@ -2802,11 +2802,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (!onlySelect && initialDialogsType == 0) { fragmentLocationContextView = new FragmentContextView(context, this, true); - fragmentLocationContextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + fragmentLocationContextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); contentView.addView(fragmentLocationContextView); fragmentContextView = new FragmentContextView(context, this, false); - fragmentContextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + fragmentContextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); contentView.addView(fragmentContextView); fragmentContextView.setAdditionalContextView(fragmentLocationContextView); @@ -3310,7 +3310,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } private void updateFilterTabs(boolean force) { - if (filterTabsView == null || inPreviewMode) { + if (filterTabsView == null || inPreviewMode || searchIsShowed) { return; } if (scrimPopupWindow != null) { @@ -3742,6 +3742,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. animators.add(ObjectAnimator.ofFloat(searchViewPager, View.SCALE_X, show ? 1.0f : 1.05f)); animators.add(ObjectAnimator.ofFloat(searchViewPager, View.SCALE_Y, show ? 1.0f : 1.05f)); animators.add(ObjectAnimator.ofFloat(searchItem.getIconView(), View.ALPHA, show ? 0 : 1f)); + if (passcodeItem != null) { + animators.add(ObjectAnimator.ofFloat(passcodeItem.getIconView(), View.ALPHA, show ? 0 : 1f)); + } animators.add(ObjectAnimator.ofFloat(searchItem.getSearchContainer(), View.ALPHA, show ? 1f : 0)); if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE) { @@ -4875,7 +4878,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (MessagesController.isSupportUser(user)) { cantBlockCount++; } else { - if (lower_id == 0 || preferences.getBoolean("dialog_bar_report" + selectedDialog, true)) { + if (preferences.getBoolean("dialog_bar_report" + selectedDialog, true)) { canReportSpamCount++; } } @@ -5574,7 +5577,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } private void showFiltersHint() { - if (askingForPermissions || !getMessagesController().dialogFiltersLoaded || !getMessagesController().showFiltersTooltip || filterTabsView == null || filterTabsView.getVisibility() == View.VISIBLE || isPaused || !getUserConfig().filtersLoaded || inPreviewMode) { + if (askingForPermissions || !getMessagesController().dialogFiltersLoaded || !getMessagesController().showFiltersTooltip || filterTabsView == null || !getMessagesController().dialogFilters.isEmpty() || isPaused || !getUserConfig().filtersLoaded || inPreviewMode) { return; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index 8fda2d317..ebe1cff79 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -70,6 +70,7 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EmbedBottomSheet; +import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SearchViewPager; @@ -257,7 +258,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente private Delegate delegate; private SearchViewPager.ChatPreviewDelegate chatPreviewDelegate; public final LinearLayoutManager layoutManager; - private final LoadingView loadingView; + private final FlickerLoadingView loadingView; private boolean firstLoading = true; int animationIndex = -1; public int keyboardHeight; @@ -324,27 +325,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente layoutManager = new LinearLayoutManager(context); recyclerListView.setLayoutManager(layoutManager); - addView(loadingView = new LoadingView(context) { - @Override - public int getType() { - if (currentSearchFilter == null) { - return 1; - } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_MEDIA) { - if (!TextUtils.isEmpty(currentSearchString)) { - return 1; - } else { - return 2; - } - } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_FILES) { - return 3; - } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_MUSIC || currentSearchFilter.filterType == FiltersView.FILTER_TYPE_VOICE) { - return 4; - } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_LINKS) { - return 5; - } - return 1; - } - + addView(loadingView = new FlickerLoadingView(context) { @Override public int getColumnsCount() { return columnsCount; @@ -725,7 +706,21 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente } } firstLoading = false; - if (loadingView.getVisibility() == View.VISIBLE && recyclerListView.getChildCount() == 0) { + View progressView = null; + int progressViewPosition = -1; + for (int i = 0; i < n; i++) { + View child = recyclerListView.getChildAt(i); + if (child instanceof FlickerLoadingView) { + progressView = child; + progressViewPosition = recyclerListView.getChildAdapterPosition(child); + } + } + final View finalProgressView = progressView; + if (progressView != null) { + recyclerListView.removeView(progressView); + } + if (loadingView.getVisibility() == View.VISIBLE && recyclerListView.getChildCount() == 0 || progressView != null) { + int finalProgressViewPosition = progressViewPosition; getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -734,6 +729,11 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente AnimatorSet animatorSet = new AnimatorSet(); for (int i = 0; i < n; i++) { View child = recyclerListView.getChildAt(i); + if (finalProgressView != null) { + if (recyclerListView.getChildAdapterPosition(child) < finalProgressViewPosition) { + continue; + } + } child.setAlpha(0); int s = Math.min(recyclerListView.getMeasuredHeight(), Math.max(0, child.getTop())); int delay = (int) ((s / (float) recyclerListView.getMeasuredHeight()) * 100); @@ -751,6 +751,24 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente }); animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null); animatorSet.start(); + + if (finalProgressView != null && finalProgressView.getParent() == null) { + recyclerListView.addView(finalProgressView); + RecyclerView.LayoutManager layoutManager = recyclerListView.getLayoutManager(); + if (layoutManager != null) { + layoutManager.ignoreView(finalProgressView); + Animator animator = ObjectAnimator.ofFloat(finalProgressView, ALPHA, finalProgressView.getAlpha(), 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finalProgressView.setAlpha(1f); + layoutManager.stopIgnoringView(finalProgressView); + recyclerListView.removeView(finalProgressView); + } + }); + animator.start(); + } + } return true; } }); @@ -759,6 +777,22 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente }); }); }, (filterAndQueryIsSame && !messages.isEmpty()) ? 0 : 350); + + if (currentSearchFilter == null) { + loadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); + } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_MEDIA) { + if (!TextUtils.isEmpty(currentSearchString)) { + loadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); + } else { + loadingView.setViewType(FlickerLoadingView.PHOTOS_TYPE); + } + } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_FILES) { + loadingView.setViewType(FlickerLoadingView.FILES_TYPE); + } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_MUSIC || currentSearchFilter.filterType == FiltersView.FILTER_TYPE_VOICE) { + loadingView.setViewType(FlickerLoadingView.AUDIO_TYPE); + } else if (currentSearchFilter.filterType == FiltersView.FILTER_TYPE_LINKS) { + loadingView.setViewType(FlickerLoadingView.LINKS_TYPE); + } } public void update() { @@ -1098,7 +1132,10 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente break; case 2: default: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + flickerLoadingView.setViewType(FlickerLoadingView.LINKS_TYPE); + flickerLoadingView.setIsSingleCell(true); + view = flickerLoadingView; break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -1234,7 +1271,14 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente view = new SharedDocumentCell(mContext, SharedDocumentCell.VIEW_TYPE_GLOBAL_SEARCH); break; case 2: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + if (currentType == 2 || currentType == 4) { + flickerLoadingView.setViewType(FlickerLoadingView.AUDIO_TYPE); + } else { + flickerLoadingView.setViewType(FlickerLoadingView.FILES_TYPE); + } + flickerLoadingView.setIsSingleCell(true); + view = flickerLoadingView; break; case 3: default: @@ -1439,6 +1483,12 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente case 0: view = new DialogCell(parent.getContext(), true, false); break; + case 3: + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(parent.getContext()); + flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); + view = flickerLoadingView; + break; default: case 2: GraySectionCell cell = new GraySectionCell(parent.getContext()); @@ -1477,6 +1527,9 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente @Override public int getItemViewType(int position) { + if (position >= messages.size()) { + return 3; + } return 0; } @@ -1485,7 +1538,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente if (messages.isEmpty()) { return 0; } - return messages.size(); + return messages.size() + (endReached ? 0 : 1); } } @@ -1550,169 +1603,6 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente int getFolderId(); } - public static class LoadingView extends View { - - int gradientWidth; - LinearGradient gradient; - Paint paint = new Paint(); - private long lastUpdateTime; - private int totalTranslation; - private Matrix matrix; - RectF rectF = new RectF(); - int color0; - int color1; - - public int getType() { - return 1; - } - - public int getColumnsCount() { - return 2; - } - - public LoadingView(Context context) { - super(context); - matrix = new Matrix(); - } - - @Override - protected void onDraw(Canvas canvas) { - int color0 = Theme.getColor(Theme.key_dialogBackground); - int color1 = Theme.getColor(Theme.key_windowBackgroundGray); - if (this.color1 != color1 || this.color0 != color0) { - this.color0 = color0; - this.color1 = color1; - gradient = new LinearGradient(0, 0, 0, gradientWidth = AndroidUtilities.dp(600), new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); - paint.setShader(gradient); - } - if (getType() == 1) { - int h = 0; - while (h < getMeasuredHeight()) { - int r = AndroidUtilities.dp(25); - canvas.drawCircle(checkRtl(AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(78) >> 1), r, paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(20), AndroidUtilities.dp(140), h + AndroidUtilities.dp(28)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(42), AndroidUtilities.dp(260), h + AndroidUtilities.dp(50)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(20), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(28)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - h += AndroidUtilities.dp(78) + 1; - } - } else if (getType() == 2) { - int photoWidth = (getMeasuredWidth() - (AndroidUtilities.dp(2) * (getColumnsCount() - 1))) / getColumnsCount(); - int h = 0; - while (h < getMeasuredHeight()) { - for (int i = 0; i < getColumnsCount(); i++) { - int x = i * (photoWidth + AndroidUtilities.dp(2)); - canvas.drawRect(x, h, x + photoWidth, h + photoWidth, paint); - } - h += photoWidth + AndroidUtilities.dp(2); - } - } else if (getType() == 3) { - int h = 0; - while (h < getMeasuredHeight()) { - rectF.set(AndroidUtilities.dp(12), h + AndroidUtilities.dp(8), AndroidUtilities.dp(52), h + AndroidUtilities.dp(48)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(260), h + AndroidUtilities.dp(42)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - h += AndroidUtilities.dp(56) + 1; - } - } else if (getType() == 4) { - int h = 0; - while (h < getMeasuredHeight()) { - int radius = AndroidUtilities.dp(44) >> 1; - canvas.drawCircle(checkRtl(AndroidUtilities.dp(12) + radius), h + AndroidUtilities.dp(6) + radius, radius, paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(260), h + AndroidUtilities.dp(42)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - h += AndroidUtilities.dp(56) + 1; - } - } else if (getType() == 5) { - int h = 0; - while (h < getMeasuredHeight()) { - rectF.set(AndroidUtilities.dp(10), h + AndroidUtilities.dp(11), AndroidUtilities.dp(62), h + AndroidUtilities.dp(11 + 52)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(12), AndroidUtilities.dp(140), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34), AndroidUtilities.dp(268), h + AndroidUtilities.dp(42)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(AndroidUtilities.dp(68), h + AndroidUtilities.dp(34 + 20), AndroidUtilities.dp(120 + 68), h + AndroidUtilities.dp(42 + 20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - rectF.set(getMeasuredWidth() - AndroidUtilities.dp(50), h + AndroidUtilities.dp(12), getMeasuredWidth() - AndroidUtilities.dp(12), h + AndroidUtilities.dp(20)); - checkRtl(rectF); - canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); - - h += AndroidUtilities.dp(80); - } - } - - long newUpdateTime = SystemClock.elapsedRealtime(); - long dt = Math.abs(lastUpdateTime - newUpdateTime); - if (dt > 17) { - dt = 16; - } - lastUpdateTime = newUpdateTime; - totalTranslation += dt * getMeasuredHeight() / 400.0f; - if (totalTranslation >= getMeasuredHeight() * 2) { - totalTranslation = -gradientWidth * 2; - } - matrix.setTranslate(0, totalTranslation); - gradient.setLocalMatrix(matrix); - invalidate(); - } - - private float checkRtl(float x) { - if (LocaleController.isRTL) { - return getMeasuredWidth() - x; - } - return x; - } - - private void checkRtl(RectF rectF) { - if (LocaleController.isRTL) { - rectF.left = getMeasuredWidth() - rectF.left; - rectF.right = getMeasuredWidth() - rectF.right; - } - } - } - private void showFloatingDateView() { AndroidUtilities.cancelRunOnUIThread(hideFloatingDateRunnable); AndroidUtilities.runOnUIThread(hideFloatingDateRunnable, 650); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForwardsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForwardsActivity.java deleted file mode 100644 index da62cf241..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForwardsActivity.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 5.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2018. - */ - -package org.telegram.ui; - -import android.content.Context; -import android.os.Bundle; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ChatObject; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.R; -import org.telegram.tgnet.TLObject; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Cells.HeaderCell; -import org.telegram.ui.Cells.LoadingCell; -import org.telegram.ui.Cells.ManageChatUserCell; -import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.Components.EmptyTextProgressView; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.RecyclerListView; - -import java.util.ArrayList; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SimpleItemAnimator; - -public class ForwardsActivity extends BaseFragment { - - private ListAdapter listViewAdapter; - private EmptyTextProgressView emptyView; - private RecyclerListView listView; - private LinearLayoutManager layoutManager; - - private MessageObject messageObject; - - private ArrayList messages = new ArrayList<>(); - private boolean loading; - private boolean firstLoaded; - - private int headerRow; - private int startRow; - private int endRow; - private int privateRow; - private int sectionRow; - private int loadingRow; - private int rowCount; - - private int nextRate; - private int publicChats; - private boolean endReached; - - public ForwardsActivity(MessageObject message) { - messageObject = message; - } - - private void updateRows() { - sectionRow = -1; - headerRow = -1; - startRow = -1; - endRow = -1; - loadingRow = -1; - privateRow = -1; - - rowCount = 0; - if (firstLoaded) { - headerRow = rowCount++; - if (messageObject.messageOwner.forwards - publicChats > 0) { - privateRow = rowCount++; - } - if (!messages.isEmpty()) { - startRow = rowCount; - rowCount += messages.size(); - endRow = rowCount; - if (!endReached) { - loadingRow = rowCount++; - } - } - sectionRow = rowCount++; - } - if (listViewAdapter != null) { - listViewAdapter.notifyDataSetChanged(); - } - } - - @Override - public boolean onFragmentCreate() { - super.onFragmentCreate(); - loadChats(100); - return true; - } - - @Override - public View createView(Context context) { - actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setAllowOverlayTitle(true); - actionBar.setTitle(LocaleController.getString("Shares", R.string.Shares)); - actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { - @Override - public void onItemClick(int id) { - if (id == -1) { - finishFragment(); - } - } - }); - - fragmentView = new FrameLayout(context); - fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - FrameLayout frameLayout = (FrameLayout) fragmentView; - - emptyView = new EmptyTextProgressView(context); - emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); - emptyView.setVisibility(View.GONE); - frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - listView = new RecyclerListView(context); - listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); - ((SimpleItemAnimator) listView.getItemAnimator()).setSupportsChangeAnimations(false); - listView.setAdapter(listViewAdapter = new ListAdapter(context)); - listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); - frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - listView.setOnItemClickListener((view, position) -> { - if (position >= startRow && position < endRow) { - TLRPC.Message message = messages.get(position - startRow); - int did = (int) MessageObject.getDialogId(message); - Bundle args = new Bundle(); - if (did > 0) { - args.putInt("user_id", did); - } else { - args.putInt("chat_id", -did); - } - args.putInt("message_id", message.id); - if (getMessagesController().checkCanOpenChat(args, this)) { - presentFragment(new ChatActivity(args)); - } - } - }); - - listView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); - int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; - int totalItemCount = recyclerView.getAdapter().getItemCount(); - - if (visibleItemCount > 0) { - if (!endReached && !loading && !messages.isEmpty() && firstVisibleItem + visibleItemCount >= totalItemCount - 5) { - loadChats(100); - } - } - } - }); - - if (loading) { - emptyView.showProgress(); - } else { - emptyView.showTextView(); - } - updateRows(); - - listView.setEmptyView(emptyView); - - return fragmentView; - } - - private void loadChats(int count) { - if (loading) { - return; - } - loading = true; - if (emptyView != null && messages.isEmpty()) { - emptyView.showProgress(); - } - if (listViewAdapter != null) { - listViewAdapter.notifyDataSetChanged(); - } - TLRPC.TL_stats_getMessagePublicForwards req = new TLRPC.TL_stats_getMessagePublicForwards(); - req.msg_id = messageObject.getId(); - req.limit = count; - req.channel = getMessagesController().getInputChannel((int) -messageObject.getDialogId()); - if (!messages.isEmpty()) { - TLRPC.Message message = messages.get(messages.size()); - req.offset_id = message.id; - req.offset_peer = getMessagesController().getInputPeer((int) MessageObject.getDialogId(message)); - req.offset_rate = nextRate; - } else { - req.offset_peer = new TLRPC.TL_inputPeerEmpty(); - } - int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (error == null) { - TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; - if ((res.flags & 1) != 0) { - nextRate = res.next_rate; - } - if (res.count != 0) { - publicChats = res.count; - } else if (publicChats == 0) { - publicChats = res.messages.size(); - } - endReached = !(res instanceof TLRPC.TL_messages_messagesSlice); - getMessagesController().putChats(res.chats, false); - getMessagesController().putUsers(res.users, false); - messages.addAll(res.messages); - if (emptyView != null) { - emptyView.showTextView(); - } - } - firstLoaded = true; - loading = false; - updateRows(); - })); - getConnectionsManager().bindRequestToGuid(reqId, classGuid); - } - - @Override - public void onResume() { - super.onResume(); - AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); - if (listViewAdapter != null) { - listViewAdapter.notifyDataSetChanged(); - } - } - - private class ListAdapter extends RecyclerListView.SelectionAdapter { - - private Context mContext; - - public ListAdapter(Context context) { - mContext = context; - } - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - int type = holder.getItemViewType(); - if (type == 0) { - ManageChatUserCell cell = (ManageChatUserCell) holder.itemView; - return cell.getCurrentObject() instanceof TLObject; - } - return false; - } - - @Override - public int getItemCount() { - return rowCount; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case 0: - view = new ManageChatUserCell(mContext, 6, 2, false); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - break; - case 1: - view = new ShadowSectionCell(mContext); - break; - case 2: - HeaderCell headerCell = new HeaderCell(mContext, Theme.key_windowBackgroundWhiteBlueHeader, 21, 11, false); - headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - headerCell.setHeight(43); - view = headerCell; - break; - case 3: - default: - view = new LoadingCell(mContext, AndroidUtilities.dp(40), AndroidUtilities.dp(120)); - break; - } - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - switch (holder.getItemViewType()) { - case 0: - ManageChatUserCell userCell = (ManageChatUserCell) holder.itemView; - if (position == privateRow) { - userCell.setData(1, LocaleController.formatPluralString("Shared", messageObject.messageOwner.forwards - publicChats), LocaleController.getString("SharedToPrivateMessagesAndGroups", R.string.SharedToPrivateMessagesAndGroups), startRow != -1); - } else { - TLRPC.Message item = getItem(position); - int did = (int) MessageObject.getDialogId(item); - TLObject object; - String status = null; - if (did > 0) { - object = getMessagesController().getUser(did); - } else { - object = getMessagesController().getChat(-did); - TLRPC.Chat chat = (TLRPC.Chat) object; - if (chat.participants_count != 0) { - if (ChatObject.isChannel(chat) && !chat.megagroup) { - status = LocaleController.formatPluralString("Subscribers", chat.participants_count); - } else { - status = LocaleController.formatPluralString("Members", chat.participants_count); - } - status = String.format("%1$s, %2$s", status, LocaleController.formatDateAudio(item.date, false)); - } - } - if (object != null) { - userCell.setData(object, null, status, position != endRow - 1); - } - } - break; - case 1: - holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - break; - case 2: - HeaderCell headerCell = (HeaderCell) holder.itemView; - headerCell.setText(LocaleController.formatPluralString("Shares", messageObject.messageOwner.forwards)); - break; - } - } - - @Override - public void onViewRecycled(RecyclerView.ViewHolder holder) { - if (holder.itemView instanceof ManageChatUserCell) { - ((ManageChatUserCell) holder.itemView).recycle(); - } - } - - @Override - public int getItemViewType(int position) { - if (position == sectionRow) { - return 1; - } else if (position == headerRow) { - return 2; - } else if (position == loadingRow) { - return 3; - } - return 0; - } - - public TLRPC.Message getItem(int position) { - if (position >= startRow && position < endRow) { - return messages.get(position - startRow); - } - return null; - } - } - - @Override - public ArrayList getThemeDescriptions() { - ArrayList themeDescriptions = new ArrayList<>(); - - ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { - if (listView != null) { - int count = listView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = listView.getChildAt(a); - if (child instanceof ManageChatUserCell) { - ((ManageChatUserCell) child).update(0); - } - } - } - }; - - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, ManageChatUserCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); - themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray)); - - themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); - themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); - themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); - - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); - - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider)); - - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); - - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); - - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText)); - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText)); - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue)); - themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink)); - - return themeDescriptions; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 6b567a584..cbd4addab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -104,6 +104,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen private boolean doneButtonVisible; private boolean ignoreScrollEvent; + private int measuredContainerHeight; private int containerHeight; private int chatId; @@ -126,6 +127,9 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen private int fieldY; + private AnimatorSet currentAnimation; + int maxSize; + private final static int done_button = 1; public interface GroupCreateActivityDelegate { @@ -142,11 +146,11 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen private class SpansContainer extends ViewGroup { - private AnimatorSet currentAnimation; private boolean animationStarted; private ArrayList animators = new ArrayList<>(); private View addingSpan; private View removingSpan; + private int animationIndex = -1; public SpansContainer(Context context) { super(context); @@ -221,6 +225,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen if (containerHeight != resultHeight) { animators.add(ObjectAnimator.ofInt(GroupCreateActivity.this, "containerHeight", resultHeight)); } + measuredContainerHeight = Math.max(containerHeight, resultHeight); if (editText.getTranslationX() != fieldX) { animators.add(ObjectAnimator.ofFloat(editText, "translationX", fieldX)); } @@ -229,10 +234,19 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen } editText.setAllowDrawCursor(false); currentAnimation.playTogether(animators); + currentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + NotificationCenter.getInstance(currentAccount).onAnimationFinish(animationIndex); + requestLayout(); + super.onAnimationEnd(animation); + } + }); + animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null); currentAnimation.start(); animationStarted = true; } else { - containerHeight = currentHeight; + measuredContainerHeight = containerHeight = currentHeight; editText.setTranslationX(fieldX); editText.setTranslationY(fieldY); } @@ -241,7 +255,8 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen editText.bringPointIntoView(editText.getSelectionStart()); } } - setMeasuredDimension(width, containerHeight); + setMeasuredDimension(width, measuredContainerHeight); + listView.setTranslationY(0); } @Override @@ -446,7 +461,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width, height); - int maxSize; if (AndroidUtilities.isTablet() || height > width) { maxSize = AndroidUtilities.dp(144); } else { @@ -477,11 +491,22 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - boolean result = super.drawChild(canvas, child, drawingTime); if (child == listView || child == emptyView) { - parentLayout.drawHeaderShadow(canvas, scrollView.getMeasuredHeight()); + canvas.save(); + canvas.clipRect(child.getLeft(), Math.min(maxSize, measuredContainerHeight + containerHeight - measuredContainerHeight), child.getRight(), child.getBottom()); + boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + parentLayout.drawHeaderShadow(canvas, Math.min(maxSize, measuredContainerHeight + containerHeight - measuredContainerHeight)); + return result; + } else if (child == scrollView) { + canvas.save(); + canvas.clipRect(child.getLeft(), child.getTop(), child.getRight(), Math.min(maxSize, measuredContainerHeight + containerHeight - measuredContainerHeight)); + boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return result; + } else { + return super.drawChild(canvas, child, drawingTime); } - return result; } }; ViewGroup frameLayout = (ViewGroup) fragmentView; @@ -499,6 +524,8 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen return super.requestChildRectangleOnScreen(child, rectangle, immediate); } }; + scrollView.setClipChildren(false); + frameLayout.setClipChildren(false); scrollView.setVerticalScrollBarEnabled(false); AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_windowBackgroundWhite)); frameLayout.addView(scrollView); @@ -739,6 +766,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + editText.hideActionMode(); AndroidUtilities.hideKeyboard(editText); } } @@ -837,10 +865,13 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen @Keep public void setContainerHeight(int value) { + int dy = containerHeight - value; containerHeight = value; - if (spansContainer != null) { - spansContainer.requestLayout(); - } + int measuredH = Math.min(maxSize, measuredContainerHeight); + int currentH = Math.min(maxSize, containerHeight); + scrollView.scrollTo(0, Math.max(0, scrollView.getScrollY() - dy)); + listView.setTranslationY(currentH - measuredH); + fragmentView.invalidate(); } @Keep diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index 03ccd82a9..0fad2f84c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -42,7 +42,6 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesStorage; -import org.telegram.messenger.SharedConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLog; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java index 817ec7c02..d0995d986 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java @@ -502,7 +502,7 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC info.flags = info.flags &~ 256; } MessagesStorage.getInstance(currentAccount).updateChatInfo(info, false); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, true, null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, true); finishFragment(); } else { Toast.makeText(getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text, Toast.LENGTH_SHORT).show(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index e7c29e505..612b24d75 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -9,6 +9,8 @@ package org.telegram.ui; import android.Manifest; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; @@ -17,6 +19,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -61,12 +64,16 @@ import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.Projection; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; +import com.google.android.gms.maps.model.Circle; import com.google.android.gms.maps.model.CircleOptions; +import com.google.android.gms.maps.model.Dash; +import com.google.android.gms.maps.model.Gap; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.MapStyleOptions; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.maps.model.PatternItem; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -76,6 +83,8 @@ import org.telegram.messenger.LocationController; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; @@ -103,12 +112,15 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MapPlaceholderDrawable; +import org.telegram.ui.Components.ProximitySheet; import org.telegram.ui.Components.RecyclerListView; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -120,6 +132,7 @@ import androidx.recyclerview.widget.RecyclerView; public class LocationActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ImageView locationButton; + private ImageView proximityButton; private ActionBarMenuItem mapTypeButton; private SearchButton searchAreaButton; private LinearLayout emptyView; @@ -130,14 +143,23 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private View shadow; private ActionBarMenuItem searchItem; private MapOverlayView overlayView; + private HintView hintView; + + private boolean proximityAnimationInProgress; private GoogleMap googleMap; + private CameraUpdate moveToBounds; private MapView mapView; private CameraUpdate forceUpdate; private float yOffset; + private Circle proximityCircle; + private double previousRadius; + private boolean scrolling; + private ProximitySheet proximitySheet; + private FrameLayout mapViewClip; private LocationActivityAdapter adapter; private RecyclerListView listView; @@ -172,6 +194,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private FrameLayout lastPressedMarkerView; private boolean checkPermission = true; + private boolean checkBackgroundPermission = true; + private int askWithRadius; private boolean searching; private boolean searchWas; @@ -208,6 +232,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public final static int LOCATION_TYPE_SEND_WITH_LIVE = 1; public final static int LOCATION_TYPE_GROUP = 4; public final static int LOCATION_TYPE_GROUP_VIEW = 5; + public final static int LOCATION_TYPE_LIVE_VIEW = 6; private Runnable markAsReadRunnable; @@ -223,6 +248,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public TLRPC.User user; public TLRPC.Chat chat; public Marker marker; + public Marker directionMarker; + public boolean hasRotation; } private static class SearchButton extends TextView { @@ -265,7 +292,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public void addInfoView(Marker marker) { VenueLocation location = (VenueLocation) marker.getTag(); - if (lastPressedVenue == location) { + if (location == null || lastPressedVenue == location) { return; } showSearchPlacesButton(false); @@ -408,6 +435,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter super.onFragmentCreate(); getNotificationCenter().addObserver(this, NotificationCenter.closeChats); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.locationPermissionGranted); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.liveLocationsChanged); if (messageObject != null && messageObject.isLiveLocation()) { getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().addObserver(this, NotificationCenter.replaceMessagesObjects); @@ -419,6 +447,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public void onFragmentDestroy() { super.onFragmentDestroy(); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.locationPermissionGranted); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.liveLocationsChanged); getNotificationCenter().removeObserver(this, NotificationCenter.closeChats); getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().removeObserver(this, NotificationCenter.replaceMessagesObjects); @@ -503,7 +532,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter FileLog.e(e); } } else if (id == share_live_location) { - openShareLiveLocation(); + openShareLiveLocation(0); } } }); @@ -599,6 +628,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (changed) { fixLayoutInternal(first); first = false; + } else { + updateClipView(true); } } @@ -763,6 +794,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } } + if (!checkGpsEnabled()) { + return; + } if (messageObject != null || chatLocation != null) { if (myLocation != null && googleMap != null) { googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLocation.getLatitude(), myLocation.getLongitude()), googleMap.getMaxZoomLevel() - 4)); @@ -787,6 +821,80 @@ public class LocationActivity extends BaseFragment implements NotificationCenter removeInfoView(); }); + proximityButton = new ImageView(context); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground)); + if (Build.VERSION.SDK_INT < 21) { + Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + drawable = combinedDrawable; + } else { + StateListAnimator animator = new StateListAnimator(); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + proximityButton.setStateListAnimator(animator); + proximityButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + } + }); + } + proximityButton.setBackgroundDrawable(drawable); + proximityButton.setImageResource(R.drawable.msg_location_alert); + proximityButton.setScaleType(ImageView.ScaleType.CENTER); + proximityButton.setTag(Theme.key_location_actionIcon); + proximityButton.setContentDescription(LocaleController.getString("AccDescrLocationNotify", R.string.AccDescrLocationNotify)); + mapViewClip.addView(proximityButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.TOP, 0, 12 + 50, 12, 0)); + proximityButton.setOnClickListener(v -> { + if (getParentActivity() == null || myLocation == null || !checkGpsEnabled()) { + return; + } + if (hintView != null) { + hintView.hide(); + } + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + preferences.edit().putInt("proximityhint", 3).commit(); + LocationController.SharingLocationInfo info = getLocationController().getSharingLocationInfo(dialogId); + if (info != null && info.proximityMeters > 0) { + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); + getLocationController().setProximityLocation(dialogId, 0, true); + if (proximityCircle != null) { + proximityCircle.remove(); + proximityCircle = null; + } + return; + } + openProximityAlert(); + }); + TLRPC.Chat chat = null; + if ((int) dialogId < 0) { + chat = getMessagesController().getChat(-(int) dialogId); + } + if (messageObject == null || !messageObject.isLiveLocation() || messageObject.isExpiredLiveLocation(getConnectionsManager().getCurrentTime()) || ChatObject.isChannel(chat) && !chat.megagroup) { + proximityButton.setVisibility(View.GONE); + } else { + LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(dialogId); + if (myInfo != null && myInfo.proximityMeters > 0) { + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + } else { + if ((int) dialogId > 0 && messageObject.getFromChatId() == getUserConfig().getClientUserId()) { + proximityButton.setVisibility(View.INVISIBLE); + proximityButton.setAlpha(0.0f); + proximityButton.setScaleX(0.4f); + proximityButton.setScaleY(0.4f); + } + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); + } + } + + hintView = new HintView(context, 6, true); + hintView.setVisibility(View.INVISIBLE); + hintView.setShowingDuration(4000); + mapViewClip.addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); + emptyView = new LinearLayout(context); emptyView.setOrientation(LinearLayout.VERTICAL); emptyView.setGravity(Gravity.CENTER_HORIZONTAL); @@ -843,7 +951,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } }); - adapter.setUpdateRunnable(this::updateClipView); + adapter.setUpdateRunnable(() -> updateClipView(false)); listView.setVerticalScrollBarEnabled(false); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); @@ -859,7 +967,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - updateClipView(); + updateClipView(false); if (forceUpdate != null) { yOffset += dy; } @@ -902,7 +1010,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (googleMap != null) { googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(chatLocation.geo_point.lat, chatLocation.geo_point._long), googleMap.getMaxZoomLevel() - 4)); } - } else if (position == 1 && messageObject != null && !messageObject.isLiveLocation()) { + } else if (position == 1 && messageObject != null && (!messageObject.isLiveLocation() || locationType == LOCATION_TYPE_LIVE_VIEW)) { if (googleMap != null) { googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long), googleMap.getMaxZoomLevel() - 4)); } @@ -931,7 +1039,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter getLocationController().removeSharingLocation(dialogId); finishFragment(); } else { - openShareLiveLocation(); + openShareLiveLocation(0); } } else { Object object = adapter.getItem(position); @@ -1016,6 +1124,17 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } return super.onInterceptTouchEvent(ev); } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + AndroidUtilities.runOnUIThread(() -> { + if (moveToBounds != null) { + googleMap.moveCamera(moveToBounds); + moveToBounds = null; + } + }); + } }; final MapView map = mapView; new Thread(() -> { @@ -1051,21 +1170,18 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }).start(); if (messageObject == null && chatLocation == null) { - if (locationType == LOCATION_TYPE_GROUP && dialogId != 0) { - TLRPC.Chat chat = getMessagesController().getChat(-(int) dialogId); - if (chat != null) { - FrameLayout frameLayout1 = new FrameLayout(context); - frameLayout1.setBackgroundResource(R.drawable.livepin); - mapViewClip.addView(frameLayout1, LayoutHelper.createFrame(62, 76, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); + if (chat != null && locationType == LOCATION_TYPE_GROUP && dialogId != 0) { + FrameLayout frameLayout1 = new FrameLayout(context); + frameLayout1.setBackgroundResource(R.drawable.livepin); + mapViewClip.addView(frameLayout1, LayoutHelper.createFrame(62, 76, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); - BackupImageView backupImageView = new BackupImageView(context); - backupImageView.setRoundRadius(AndroidUtilities.dp(26)); - backupImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", new AvatarDrawable(chat), chat); - frameLayout1.addView(backupImageView, LayoutHelper.createFrame(52, 52, Gravity.LEFT | Gravity.TOP, 5, 5, 0, 0)); + BackupImageView backupImageView = new BackupImageView(context); + backupImageView.setRoundRadius(AndroidUtilities.dp(26)); + backupImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", new AvatarDrawable(chat), chat); + frameLayout1.addView(backupImageView, LayoutHelper.createFrame(52, 52, Gravity.LEFT | Gravity.TOP, 5, 5, 0, 0)); - markerImageView = frameLayout1; - markerImageView.setTag(1); - } + markerImageView = frameLayout1; + markerImageView.setTag(1); } if (markerImageView == null) { @@ -1124,6 +1240,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter adapter.setMessageObject(messageObject); } } + if (messageObject != null && locationType == LOCATION_TYPE_LIVE_VIEW) { + adapter.setMessageObject(messageObject); + } shadow = new View(context) { @@ -1208,11 +1327,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else if (liveLocation.chat != null && liveLocation.chat.photo != null) { photo = liveLocation.chat.photo.photo_small; } - result = Bitmap.createBitmap(AndroidUtilities.dp(62), AndroidUtilities.dp(76), Bitmap.Config.ARGB_8888); + result = Bitmap.createBitmap(AndroidUtilities.dp(62), AndroidUtilities.dp(85), Bitmap.Config.ARGB_8888); result.eraseColor(Color.TRANSPARENT); Canvas canvas = new Canvas(result); - Drawable drawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.livepin); - drawable.setBounds(0, 0, AndroidUtilities.dp(62), AndroidUtilities.dp(76)); + Drawable drawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.map_pin_photo); + drawable.setBounds(0, 0, AndroidUtilities.dp(62), AndroidUtilities.dp(85)); drawable.draw(canvas); Paint roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -1224,13 +1343,13 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (bitmap != null) { BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Matrix matrix = new Matrix(); - float scale = AndroidUtilities.dp(52) / (float) bitmap.getWidth(); - matrix.postTranslate(AndroidUtilities.dp(5), AndroidUtilities.dp(5)); + float scale = AndroidUtilities.dp(50) / (float) bitmap.getWidth(); + matrix.postTranslate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); matrix.postScale(scale, scale); roundPaint.setShader(shader); shader.setLocalMatrix(matrix); - bitmapRect.set(AndroidUtilities.dp(5), AndroidUtilities.dp(5), AndroidUtilities.dp(52 + 5), AndroidUtilities.dp(52 + 5)); - canvas.drawRoundRect(bitmapRect, AndroidUtilities.dp(26), AndroidUtilities.dp(26), roundPaint); + bitmapRect.set(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(50 + 6), AndroidUtilities.dp(50 + 6)); + canvas.drawRoundRect(bitmapRect, AndroidUtilities.dp(25), AndroidUtilities.dp(25), roundPaint); } } else { AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -1239,8 +1358,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else if (liveLocation.chat != null) { avatarDrawable.setInfo(liveLocation.chat); } - canvas.translate(AndroidUtilities.dp(5), AndroidUtilities.dp(5)); - avatarDrawable.setBounds(0, 0, AndroidUtilities.dp(52.2f), AndroidUtilities.dp(52.2f)); + canvas.translate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + avatarDrawable.setBounds(0, 0, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); avatarDrawable.draw(canvas); } canvas.restore(); @@ -1263,23 +1382,120 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } - private void openShareLiveLocation() { - if (delegate == null || getParentActivity() == null || myLocation == null) { + private void openProximityAlert() { + if (proximityCircle == null) { + createCircle(500); + } else { + previousRadius = proximityCircle.getRadius(); + } + + TLRPC.User user = null; + if ((int) dialogId > 0) { + user = getMessagesController().getUser((int) dialogId); + } + proximitySheet = new ProximitySheet(getParentActivity(), user, (move, radius) -> { + if (proximityCircle != null) { + proximityCircle.setRadius(radius); + if (move) { + moveToBounds(radius, true, true); + } + } + if ((int) dialogId < 0) { + return true; + } + for (int a = 0, N = markers.size(); a < N; a++) { + LiveLocation location = markers.get(a); + if (location.object == null || UserObject.isUserSelf(location.user)) { + continue; + } + TLRPC.GeoPoint point = location.object.media.geo; + Location loc = new Location("network"); + loc.setLatitude(point.lat); + loc.setLongitude(point._long); + if (myLocation.distanceTo(loc) > radius) { + return true; + } + } + return false; + }, (move, radius) -> { + LocationController.SharingLocationInfo info = getLocationController().getSharingLocationInfo(dialogId); + if (info == null) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("ShareLocationAlertTitle", R.string.ShareLocationAlertTitle)); + builder.setMessage(LocaleController.getString("ShareLocationAlertText", R.string.ShareLocationAlertText)); + builder.setPositiveButton(LocaleController.getString("ShareLocationAlertButton", R.string.ShareLocationAlertButton), (dialog, id) -> shareLiveLocation(900, radius)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + return false; + } + proximitySheet.setRadiusSet(); + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + getLocationController().setProximityLocation(dialogId, radius, true); + return true; + }, () -> { + if (googleMap != null) { + googleMap.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + } + if (!proximitySheet.getRadiusSet()) { + if (previousRadius > 0) { + proximityCircle.setRadius(previousRadius); + } else if (proximityCircle != null) { + proximityCircle.remove(); + proximityCircle = null; + } + } + proximitySheet = null; + }); + FrameLayout frameLayout = (FrameLayout) fragmentView; + frameLayout.addView(proximitySheet, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + proximitySheet.show(); + } + + private void openShareLiveLocation(int proximityRadius) { + if (delegate == null || getParentActivity() == null || myLocation == null || !checkGpsEnabled()) { return; } + if (checkBackgroundPermission && Build.VERSION.SDK_INT >= 29) { + Activity activity = getParentActivity(); + if (activity != null) { + askWithRadius = proximityRadius; + checkBackgroundPermission = false; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + int lastTime = preferences.getInt("backgroundloc", 0); + if (Math.abs(System.currentTimeMillis() / 1000 - lastTime) > 24 * 60 * 60 && activity.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { + preferences.edit().putInt("backgroundloc", (int) (System.currentTimeMillis() / 1000)).commit(); + AlertsCreator.createBackgroundLocationPermissionDialog(activity, getMessagesController().getUser(getUserConfig().getClientUserId()), () -> openShareLiveLocation(askWithRadius)).show(); + return; + } + } + } TLRPC.User user = null; if ((int) dialogId > 0) { user = getMessagesController().getUser((int) dialogId); } - showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> { - TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); - location.geo = new TLRPC.TL_geoPoint(); - location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); - location.geo._long = AndroidUtilities.fixLocationCoord(myLocation.getLongitude()); - location.period = param; - delegate.didSelectLocation(location, locationType, true, 0); + showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> shareLiveLocation(param, proximityRadius))); + } + + private void shareLiveLocation(int period, int proximityRadius) { + TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); + location.geo = new TLRPC.TL_geoPoint(); + location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); + location.geo._long = AndroidUtilities.fixLocationCoord(myLocation.getLongitude()); + location.heading = LocationController.getHeading(myLocation); + location.flags |= 1; + location.period = period; + location.proximity_notification_radius = proximityRadius; + location.flags |= 8; + delegate.didSelectLocation(location, locationType, true, 0); + if (proximityRadius > 0) { + proximitySheet.setRadiusSet(); + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + if (proximitySheet != null) { + proximitySheet.dismiss(); + } + } else { finishFragment(); - })); + } } private Bitmap[] bitmapCache = new Bitmap[7]; @@ -1357,11 +1573,29 @@ public class LocationActivity extends BaseFragment implements NotificationCenter options.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); options.anchor(0.5f, 0.907f); liveLocation.marker = googleMap.addMarker(options); + + if (!UserObject.isUserSelf(liveLocation.user)) { + MarkerOptions dirOptions = new MarkerOptions().position(latLng).flat(true); + dirOptions.anchor(0.5f, 0.5f); + liveLocation.directionMarker = googleMap.addMarker(dirOptions); + + if (message.media.heading != 0) { + liveLocation.directionMarker.setRotation(message.media.heading); + liveLocation.directionMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.map_pin_cone2)); + liveLocation.hasRotation = true; + } else { + liveLocation.directionMarker.setRotation(0); + liveLocation.directionMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.map_pin_circle)); + liveLocation.hasRotation = false; + } + } + markers.add(liveLocation); markersMap.put(liveLocation.id, liveLocation); LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(dialogId); if (liveLocation.id == getUserConfig().getClientUserId() && myInfo != null && liveLocation.object.id == myInfo.mid && myLocation != null) { - liveLocation.marker.setPosition(new LatLng(myLocation.getLatitude(), myLocation.getLongitude())); + LatLng latLng1 = new LatLng(myLocation.getLatitude(), myLocation.getLongitude()); + liveLocation.marker.setPosition(latLng1); } } } catch (Exception e) { @@ -1371,6 +1605,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter liveLocation.object = message; liveLocation.marker.setPosition(latLng); } + if (proximitySheet != null) { + proximitySheet.updateText(true, true); + } return liveLocation; } @@ -1392,6 +1629,14 @@ public class LocationActivity extends BaseFragment implements NotificationCenter options.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); options.anchor(0.5f, 0.907f); liveLocation.marker = googleMap.addMarker(options); + + if (!UserObject.isUserSelf(liveLocation.user)) { + MarkerOptions dirOptions = new MarkerOptions().position(latLng).flat(true); + dirOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_pin_circle)); + dirOptions.anchor(0.5f, 0.5f); + liveLocation.directionMarker = googleMap.addMarker(dirOptions); + } + markers.add(liveLocation); markersMap.put(liveLocation.id, liveLocation); } @@ -1499,34 +1744,65 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (checkGpsEnabled && getParentActivity() != null) { checkGpsEnabled = false; - if (!getParentActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { - return; - } - try { - LocationManager lm = (LocationManager) ApplicationLoader.applicationContext.getSystemService(Context.LOCATION_SERVICE); - if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("GpsDisabledAlertTitle", R.string.GpsDisabledAlertTitle)); - builder.setMessage(LocaleController.getString("GpsDisabledAlertText", R.string.GpsDisabledAlertText)); - builder.setPositiveButton(LocaleController.getString("ConnectingToProxyEnable", R.string.ConnectingToProxyEnable), (dialog, id) -> { - if (getParentActivity() == null) { - return; - } - try { - getParentActivity().startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - } catch (Exception ignore) { + checkGpsEnabled(); + } - } - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - } - } catch (Exception e) { - FileLog.e(e); + if (proximityButton != null && proximityButton.getVisibility() == View.VISIBLE) { + LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(dialogId); + if (myInfo != null && myInfo.proximityMeters > 0) { + createCircle(myInfo.proximityMeters); } } } + private boolean checkGpsEnabled() { + if (!getParentActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { + return true; + } + try { + LocationManager lm = (LocationManager) ApplicationLoader.applicationContext.getSystemService(Context.LOCATION_SERVICE); + if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("GpsDisabledAlertTitle", R.string.GpsDisabledAlertTitle)); + builder.setMessage(LocaleController.getString("GpsDisabledAlertText", R.string.GpsDisabledAlertText)); + builder.setPositiveButton(LocaleController.getString("ConnectingToProxyEnable", R.string.ConnectingToProxyEnable), (dialog, id) -> { + if (getParentActivity() == null) { + return; + } + try { + getParentActivity().startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + } catch (Exception ignore) { + + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + return false; + } + } catch (Exception e) { + FileLog.e(e); + } + return true; + } + + private void createCircle(int meters) { + List PATTERN_POLYGON_ALPHA = Arrays.asList(new Gap(20), new Dash(20)); + + CircleOptions circleOptions = new CircleOptions(); + circleOptions.center(new LatLng(myLocation.getLatitude(), myLocation.getLongitude())); + circleOptions.radius(meters); + if (isActiveThemeDark()) { + circleOptions.strokeColor(0xffffffff); + circleOptions.fillColor(0x20ffffff); + } else { + circleOptions.strokeColor(0xff000000); + circleOptions.fillColor(0x20000000); + } + circleOptions.strokePattern(PATTERN_POLYGON_ALPHA); + circleOptions.strokeWidth(2); + proximityCircle = googleMap.addCircle(circleOptions); + } + private void removeInfoView() { if (lastPressedMarker != null) { markerImageView.setVisibility(View.VISIBLE); @@ -1588,13 +1864,32 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } mapViewClip.addView(overlayView, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); } - updateClipView(); + updateClipView(false); + maybeShowProximityHint(); } else if (fragmentView != null) { ((FrameLayout) fragmentView).addView(mapView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); } } } + private void maybeShowProximityHint() { + if (proximityButton == null || proximityButton.getVisibility() != View.VISIBLE || proximityAnimationInProgress) { + return; + } + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + int val = preferences.getInt("proximityhint", 0); + if (val < 3) { + preferences.edit().putInt("proximityhint", ++val).commit(); + if ((int) dialogId > 0) { + TLRPC.User user = getMessagesController().getUser((int) dialogId); + hintView.setOverrideText(LocaleController.formatString("ProximityTooltioUser", R.string.ProximityTooltioUser, UserObject.getFirstName(user))); + } else { + hintView.setOverrideText(LocaleController.getString("ProximityTooltioGroup", R.string.ProximityTooltioGroup)); + } + hintView.showForView(proximityButton, true); + } + } + private void showResults() { if (adapter.getItemCount() == 0) { return; @@ -1611,7 +1906,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter listView.smoothScrollBy(0, offset); } - private void updateClipView() { + private void updateClipView(boolean fromLayout) { int height = 0; int top; RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(0); @@ -1648,25 +1943,31 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } float translationY = Math.min(overScrollHeight - mapTypeButton.getMeasuredHeight() - AndroidUtilities.dp(64 + (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE ? 30 : 10)), -top); mapTypeButton.setTranslationY(translationY); + proximityButton.setTranslationY(translationY); + if (hintView != null) { + hintView.setExtraTranslationY(translationY); + } if (searchAreaButton != null) { searchAreaButton.setTranslation(translationY); } if (markerImageView != null) { markerImageView.setTranslationY(markerTop = -top - AndroidUtilities.dp(markerImageView.getTag() == null ? 48 : 69) + height / 2); } - layoutParams = (FrameLayout.LayoutParams) mapView.getLayoutParams(); - if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); - if (googleMap != null) { - googleMap.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); - } - mapView.setLayoutParams(layoutParams); - } - if (overlayView != null) { - layoutParams = (FrameLayout.LayoutParams) overlayView.getLayoutParams(); + if (!fromLayout) { + layoutParams = (FrameLayout.LayoutParams) mapView.getLayoutParams(); if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); - overlayView.setLayoutParams(layoutParams); + if (googleMap != null) { + googleMap.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + } + mapView.setLayoutParams(layoutParams); + } + if (overlayView != null) { + layoutParams = (FrameLayout.LayoutParams) overlayView.getLayoutParams(); + if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { + layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + overlayView.setLayoutParams(layoutParams); + } } } } @@ -1679,7 +1980,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (viewHeight == 0) { return; } - if (locationType == 2) { + if (locationType == LOCATION_TYPE_LIVE_VIEW) { + overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; + } else if (locationType == 2) { overScrollHeight = viewHeight - AndroidUtilities.dp(66 + 7) - height; } else { overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; @@ -1726,13 +2029,13 @@ public class LocationActivity extends BaseFragment implements NotificationCenter top = 0; } layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); - updateClipView(); + updateClipView(false); listView.post(() -> { layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); - updateClipView(); + updateClipView(false); }); } else { - updateClipView(); + updateClipView(false); } } } @@ -1758,7 +2061,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter LiveLocation liveLocation = markersMap.get(getUserConfig().getClientUserId()); LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(dialogId); if (liveLocation != null && myInfo != null && liveLocation.object.id == myInfo.mid) { - liveLocation.marker.setPosition(new LatLng(location.getLatitude(), location.getLongitude())); + LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); + liveLocation.marker.setPosition(latLng); + if (liveLocation.directionMarker != null) { + liveLocation.directionMarker.setPosition(latLng); + } } if (messageObject == null && chatLocation == null && googleMap != null) { LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); @@ -1782,6 +2089,12 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else { adapter.setGpsLocation(myLocation); } + if (proximitySheet != null) { + proximitySheet.updateText(true, true); + } + if (proximityCircle != null) { + proximityCircle.setCenter(new LatLng(myLocation.getLatitude(), myLocation.getLongitude())); + } } public void setMessageObject(MessageObject message) { @@ -1837,9 +2150,23 @@ public class LocationActivity extends BaseFragment implements NotificationCenter builder.include(latLng); } addUserMarker(message); + if (proximityButton.getVisibility() != View.GONE && MessageObject.getFromChatId(message) != getUserConfig().getClientUserId()) { + proximityButton.setVisibility(View.VISIBLE); + proximityAnimationInProgress = true; + proximityButton.animate().alpha(1.0f).scaleX(1.0f).scaleY(1.0f).setDuration(180).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + proximityAnimationInProgress = false; + maybeShowProximityHint(); + } + }).start(); + } } } if (builder != null) { + if (firstFocus) { + listView.smoothScrollBy(0, AndroidUtilities.dp(66 * 1.5f)); + } firstFocus = false; adapter.setLiveLocations(markers); if (messageObject.isLiveLocation()) { @@ -1853,7 +2180,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter bounds = builder.build(); if (messages.size() > 1) { try { - googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, AndroidUtilities.dp(60))); + moveToBounds = CameraUpdateFactory.newLatLngBounds(bounds, AndroidUtilities.dp(80)); + googleMap.moveCamera(moveToBounds); + moveToBounds = null; } catch (Exception e) { FileLog.e(e); } @@ -1865,6 +2194,63 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } + private void moveToBounds(int radius, boolean self, boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + builder.include(new LatLng(myLocation.getLatitude(), myLocation.getLongitude())); + if (self) { + try { + radius = Math.max(radius, 250); + LatLngBounds bounds = builder.build(); + LatLng center = bounds.getCenter(); + LatLng northEast = move(center, radius, radius); + LatLng southWest = move(center, -radius, -radius); + builder.include(southWest); + builder.include(northEast); + bounds = builder.build(); + try { + int height = (int) (proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(40) + mapViewClip.getTranslationY()); + googleMap.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + if (animated) { + googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), 500, null); + } else { + googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); + } + } catch (Exception e) { + FileLog.e(e); + } + } catch (Exception ignore) { + + } + } else { + int date = getConnectionsManager().getCurrentTime(); + for (int a = 0, N = markers.size(); a < N; a++) { + TLRPC.Message message = markers.get(a).object; + if (message.date + message.media.period > date) { + LatLng latLng = new LatLng(message.media.geo.lat, message.media.geo._long); + builder.include(latLng); + } + } + try { + LatLngBounds bounds = builder.build(); + LatLng center = bounds.getCenter(); + LatLng northEast = move(center, 100, 100); + LatLng southWest = move(center, -100, -100); + builder.include(southWest); + builder.include(northEast); + bounds = builder.build(); + try { + int height = proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(100); + googleMap.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); + } catch (Exception e) { + FileLog.e(e); + } + } catch (Exception ignore) { + + } + } + } + private boolean getRecentLocations() { ArrayList messages = getLocationController().locationsCache.get(messageObject.getDialogId()); if (messages != null && messages.isEmpty()) { @@ -1919,6 +2305,24 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return messages != null; } + private double bearingBetweenLocations(LatLng latLng1, LatLng latLng2) { + double lat1 = latLng1.latitude * Math.PI / 180; + double long1 = latLng1.longitude * Math.PI / 180; + double lat2 = latLng2.latitude * Math.PI / 180; + double long2 = latLng2.longitude * Math.PI / 180; + double dLon = (long2 - long1); + + double y = Math.sin(dLon) * Math.cos(lat2); + double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); + + double brng = Math.atan2(y, x); + + brng = Math.toDegrees(brng); + brng = (brng + 360) % 360; + + return brng; + } + @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { @@ -1932,6 +2336,10 @@ public class LocationActivity extends BaseFragment implements NotificationCenter FileLog.e(e); } } + } else if (id == NotificationCenter.liveLocationsChanged) { + if (adapter != null) { + adapter.updateLiveLocationCell(); + } } else if (id == NotificationCenter.didReceiveNewMessages) { boolean scheduled = (Boolean) args[2]; if (scheduled) { @@ -1948,6 +2356,15 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (messageObject.isLiveLocation()) { addUserMarker(messageObject.messageOwner); added = true; + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { + int lowerId = (int) messageObject.getDialogId(); + if (lowerId > 0) { + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); + if (proximityCircle != null) { + proximityCircle.remove(); + proximityCircle = null; + } + } } } if (added && adapter != null) { @@ -1970,13 +2387,34 @@ public class LocationActivity extends BaseFragment implements NotificationCenter LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(did); if (myInfo == null || myInfo.mid != messageObject.getId()) { liveLocation.object = messageObject.messageOwner; - liveLocation.marker.setPosition(new LatLng(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long)); + LatLng latLng = new LatLng(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long); + liveLocation.marker.setPosition(latLng); + if (liveLocation.directionMarker != null) { + LatLng oldLocation = liveLocation.directionMarker.getPosition(); + liveLocation.directionMarker.setPosition(latLng); + if (messageObject.messageOwner.media.heading != 0) { + liveLocation.directionMarker.setRotation(messageObject.messageOwner.media.heading); + if (!liveLocation.hasRotation) { + liveLocation.directionMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.map_pin_cone2)); + liveLocation.hasRotation = true; + } + } else { + if (liveLocation.hasRotation) { + liveLocation.directionMarker.setRotation(0); + liveLocation.directionMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.map_pin_circle)); + liveLocation.hasRotation = false; + } + } + } } updated = true; } } if (updated && adapter != null) { adapter.updateLiveLocations(); + if (proximitySheet != null) { + proximitySheet.updateText(true, true); + } } } } @@ -1994,6 +2432,15 @@ public class LocationActivity extends BaseFragment implements NotificationCenter onResumeCalled = false; } + @Override + public boolean onBackPressed() { + if (proximitySheet != null) { + proximitySheet.dismiss(); + return false; + } + return super.onBackPressed(); + } + @Override public void onResume() { super.onResume(); @@ -2030,6 +2477,13 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } + @Override + public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == 30) { + openShareLiveLocation(askWithRadius); + } + } + @Override public void onLowMemory() { super.onLowMemory(); @@ -2071,11 +2525,19 @@ public class LocationActivity extends BaseFragment implements NotificationCenter currentMapStyleDark = true; MapStyleOptions style = MapStyleOptions.loadRawResourceStyle(ApplicationLoader.applicationContext, R.raw.mapstyle_night); googleMap.setMapStyle(style); + if (proximityCircle != null) { + proximityCircle.setStrokeColor(0xffffffff); + proximityCircle.setFillColor(0x20ffffff); + } } } else { if (currentMapStyleDark) { currentMapStyleDark = false; googleMap.setMapStyle(null); + if (proximityCircle != null) { + proximityCircle.setStrokeColor(0xff000000); + proximityCircle.setFillColor(0x20000000); + } } } } @@ -2113,6 +2575,10 @@ public class LocationActivity extends BaseFragment implements NotificationCenter themeDescriptions.add(new ThemeDescription(mapTypeButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_location_actionBackground)); themeDescriptions.add(new ThemeDescription(mapTypeButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_location_actionPressedBackground)); + themeDescriptions.add(new ThemeDescription(proximityButton, 0, null, null, null, cellDelegate, Theme.key_location_actionIcon)); + themeDescriptions.add(new ThemeDescription(proximityButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_location_actionBackground)); + themeDescriptions.add(new ThemeDescription(proximityButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_location_actionPressedBackground)); + themeDescriptions.add(new ThemeDescription(searchAreaButton, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_location_actionActiveIcon)); themeDescriptions.add(new ThemeDescription(searchAreaButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_location_actionBackground)); themeDescriptions.add(new ThemeDescription(searchAreaButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_location_actionPressedBackground)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index d59f5e55a..42aef8d74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -1223,7 +1223,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } if (!AndroidUtilities.isTablet()) { - frameLayout.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, 8, 0, 0)); + frameLayout.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 8, 0, 0)); } frameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessageStatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MessageStatisticActivity.java new file mode 100644 index 000000000..ed7ad469f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessageStatisticActivity.java @@ -0,0 +1,982 @@ +/* + * This is the source code of Telegram for Android v. 5.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2018. + */ + +package org.telegram.ui; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import org.json.JSONException; +import org.json.JSONObject; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.DownloadController; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.LruCache; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.BackDrawable; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.DialogCell; +import org.telegram.ui.Cells.EmptyCell; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.LoadingCell; +import org.telegram.ui.Cells.ManageChatUserCell; +import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Charts.BaseChartView; +import org.telegram.ui.Charts.data.ChartData; +import org.telegram.ui.Charts.data.StackLinearChartData; +import org.telegram.ui.Charts.view_data.ChartHeaderView; +import org.telegram.ui.Components.ChatAvatarContainer; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.EmptyTextProgressView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieImageView; +import org.telegram.ui.Components.RecyclerListView; + +import java.util.ArrayList; + +import androidx.collection.ArraySet; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +public class MessageStatisticActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + + private TLRPC.ChatFull chat; + private final int chatId; + private final int messageId; + private ListAdapter listViewAdapter; + private EmptyTextProgressView emptyView; + private RecyclerListView listView; + private LinearLayoutManager layoutManager; + + private MessageObject messageObject; + private StatisticActivity.ChartViewData interactionsViewData; + private LruCache childDataCache = new LruCache<>(15); + private StatisticActivity.ZoomCancelable lastCancelable; + + private ArrayList messages = new ArrayList<>(); + private boolean statsLoaded; + private boolean loading; + private boolean firstLoaded; + + private int headerRow; + private int startRow; + private int endRow; + private int loadingRow; + private int interactionsChartRow; + private int overviewRow; + private int overviewHeaderRow; + private int emptyRow; + private int rowCount; + + ArraySet shadowDivideCells = new ArraySet<>(); + + private RLottieImageView imageView; + private LinearLayout progressLayout; + + private int nextRate; + private int publicChats; + private boolean endReached; + + ImageReceiver thumbImage; + boolean drawPlay; + + private final Runnable showProgressbar = new Runnable() { + @Override + public void run() { + progressLayout.animate().alpha(1f).setDuration(230); + } + }; + private FrameLayout listContainer; + private ChatAvatarContainer avatarContainer; + private BaseChartView.SharedUiComponents sharedUi; + + public MessageStatisticActivity(MessageObject message) { + messageObject = message; + + if (messageObject.messageOwner.fwd_from == null) { + chatId = messageObject.getChatId(); + messageId = messageObject.getId(); + } else { + chatId = -messageObject.getFromChatId(); + messageId = messageObject.messageOwner.fwd_msg_id; + } + this.chat = getMessagesController().getChatFull(chatId); + } + + private void updateRows() { + shadowDivideCells.clear(); + headerRow = -1; + startRow = -1; + endRow = -1; + loadingRow = -1; + interactionsChartRow = -1; + overviewHeaderRow = -1; + overviewRow = -1; + + rowCount = 0; + if (firstLoaded && statsLoaded) { + AndroidUtilities.cancelRunOnUIThread(showProgressbar); + if (listContainer.getVisibility() == View.GONE) { + progressLayout.animate().alpha(0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + progressLayout.setVisibility(View.GONE); + } + }); + listContainer.setVisibility(View.VISIBLE); + listContainer.setAlpha(0f); + listContainer.animate().alpha(1f).start(); + } + + overviewHeaderRow = rowCount++; + overviewRow = rowCount++; + shadowDivideCells.add(rowCount++); + if (interactionsViewData != null) { + interactionsChartRow = rowCount++; + shadowDivideCells.add(rowCount++); + } + + if (!messages.isEmpty()) { + headerRow = rowCount++; + startRow = rowCount; + rowCount += messages.size(); + endRow = rowCount; + emptyRow = rowCount++; + shadowDivideCells.add(rowCount++); + + if (!endReached) { + loadingRow = rowCount++; + } + } + } + if (listViewAdapter != null) { + listViewAdapter.notifyDataSetChanged(); + } + } + + @Override + public boolean onFragmentCreate() { + super.onFragmentCreate(); + if (chat != null) { + loadStat(); + loadChats(100); + } else { + MessagesController.getInstance(currentAccount).loadFullChat(chatId, classGuid, true); + } + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad); + return true; + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.chatInfoDidLoad) { + TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; + if (chat == null && chatFull.id == chatId) { + TLRPC.Chat chatLocal = getMessagesController().getChat(chatId); + if (chatLocal != null) { + avatarContainer.setChatAvatar(chatLocal); + avatarContainer.setTitle(chatLocal.title); + } + chat = chatFull; + loadStat(); + loadChats(100); + updateMenu(); + } + } + } + + @Override + public View createView(Context context) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + + fragmentView = new FrameLayout(context); + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + FrameLayout frameLayout = (FrameLayout) fragmentView; + + emptyView = new EmptyTextProgressView(context); + emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + emptyView.setVisibility(View.GONE); + + progressLayout = new LinearLayout(context); + progressLayout.setOrientation(LinearLayout.VERTICAL); + + imageView = new RLottieImageView(context); + imageView.setAutoRepeat(true); + imageView.setAnimation(R.raw.statistic_preload, 120, 120); + imageView.playAnimation(); + + TextView loadingTitle = new TextView(context); + loadingTitle.setTextSize(20); + loadingTitle.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + loadingTitle.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle)); + loadingTitle.setTag(Theme.key_player_actionBarTitle); + loadingTitle.setText(LocaleController.getString("LoadingStats", R.string.LoadingStats)); + loadingTitle.setGravity(Gravity.CENTER_HORIZONTAL); + + TextView loadingSubtitle = new TextView(context); + loadingSubtitle.setTextSize(15); + loadingSubtitle.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + loadingSubtitle.setTag(Theme.key_player_actionBarSubtitle); + loadingSubtitle.setText(LocaleController.getString("LoadingStatsDescription", R.string.LoadingStatsDescription)); + loadingSubtitle.setGravity(Gravity.CENTER_HORIZONTAL); + + progressLayout.addView(imageView, LayoutHelper.createLinear(120, 120, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 20)); + progressLayout.addView(loadingTitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 10)); + progressLayout.addView(loadingSubtitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); + progressLayout.setAlpha(0); + + frameLayout.addView(progressLayout, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 30)); + + listView = new RecyclerListView(context); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + ((SimpleItemAnimator) listView.getItemAnimator()).setSupportsChangeAnimations(false); + listView.setAdapter(listViewAdapter = new ListAdapter(context)); + listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); + + listView.setOnItemClickListener((view, position) -> { + if (position >= startRow && position < endRow) { + TLRPC.Message message = messages.get(position - startRow); + int did = (int) MessageObject.getDialogId(message); + Bundle args = new Bundle(); + if (did > 0) { + args.putInt("user_id", did); + } else { + args.putInt("chat_id", -did); + } + args.putInt("message_id", message.id); + args.putBoolean("need_remove_previous_same_chat_activity", false); + if (getMessagesController().checkCanOpenChat(args, this)) { + presentFragment(new ChatActivity(args)); + } + } + }); + + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); + int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; + int totalItemCount = recyclerView.getAdapter().getItemCount(); + + if (visibleItemCount > 0) { + if (!endReached && !loading && !messages.isEmpty() && firstVisibleItem + visibleItemCount >= totalItemCount - 5 && statsLoaded) { + loadChats(100); + } + } + } + }); + emptyView.showTextView(); + + listContainer = new FrameLayout(context); + listContainer.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listContainer.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listContainer.setVisibility(View.GONE); + frameLayout.addView(listContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + AndroidUtilities.runOnUIThread(showProgressbar, 300); + + updateRows(); + listView.setEmptyView(emptyView); + + avatarContainer = new ChatAvatarContainer(context, null, false) { + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + thumbImage.setImageCoords(avatarContainer.getSubtitleTextView().getX(), avatarContainer.getSubtitleTextView().getY(), AndroidUtilities.dp(18), AndroidUtilities.dp(18)); + thumbImage.draw(canvas); + if (drawPlay) { + int x = (int) (thumbImage.getCenterX() - Theme.dialogs_playDrawable.getIntrinsicWidth() / 2); + int y = (int) (thumbImage.getCenterY() - Theme.dialogs_playDrawable.getIntrinsicHeight() / 2); + Theme.dialogs_playDrawable.setBounds(x, y, x + Theme.dialogs_playDrawable.getIntrinsicWidth(), y + Theme.dialogs_playDrawable.getIntrinsicHeight()); + Theme.dialogs_playDrawable.draw(canvas); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + thumbImage.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + thumbImage.onDetachedFromWindow(); + } + }; + + thumbImage = new ImageReceiver(); + thumbImage.setParentView(avatarContainer); + thumbImage.setRoundRadius(AndroidUtilities.dp(2)); + actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0)); + + TLRPC.Chat chatLocal = getMessagesController().getChat(chatId); + if (chatLocal != null) { + avatarContainer.setChatAvatar(chatLocal); + avatarContainer.setTitle(chatLocal.title); + } + + boolean hasThumb = false; + + if (!messageObject.needDrawBluredPreview() && (messageObject.isPhoto() || messageObject.isNewGif() || messageObject.isVideo())) { + String type = messageObject.isWebpage() ? messageObject.messageOwner.media.webpage.type : null; + if (!("app".equals(type) || "profile".equals(type) || "article".equals(type))) { + TLRPC.PhotoSize smallThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); + TLRPC.PhotoSize bigThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (smallThumb == bigThumb) { + bigThumb = null; + } + if (smallThumb != null) { + hasThumb = true; + drawPlay = messageObject.isVideo(); + String fileName = FileLoader.getAttachFileName(bigThumb); + if (messageObject.mediaExists || DownloadController.getInstance(currentAccount).canDownloadMedia(messageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { + int size; + if (messageObject.type == MessageObject.TYPE_PHOTO) { + size = bigThumb != null ? bigThumb.size : 0; + } else { + size = 0; + } + thumbImage.setImage(ImageLocation.getForObject(bigThumb, messageObject.photoThumbsObject), "20_20", ImageLocation.getForObject(smallThumb, messageObject.photoThumbsObject), "20_20", size, null, messageObject, 0); + } else { + thumbImage.setImage(null, null, ImageLocation.getForObject(smallThumb, messageObject.photoThumbsObject), "20_20", null, messageObject, 0); + } + } + } + } + + CharSequence message; + if (!TextUtils.isEmpty(messageObject.caption)) { + message = messageObject.caption; + } else if (!TextUtils.isEmpty(messageObject.messageOwner.message)) { + message = messageObject.messageText; + if (message.length() > 150) { + message = message.subSequence(0, 150); + } + message = Emoji.replaceEmoji(message, avatarContainer.getSubtitleTextView().getTextPaint().getFontMetricsInt(), AndroidUtilities.dp(17), false); + } else { + message = messageObject.messageText; + } + + if (hasThumb) { + SpannableStringBuilder builder = new SpannableStringBuilder(message); + builder.insert(0, " "); + builder.setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(18 + 6)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + avatarContainer.setSubtitle(builder); + } else { + avatarContainer.setSubtitle(messageObject.messageText); + } + actionBar.setBackButtonDrawable(new BackDrawable(false)); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(final int id) { + if (id == -1) { + finishFragment(); + } else if (id == 1) { + Bundle args = new Bundle(); + if (messageObject.messageOwner.fwd_from == null) { + args.putInt("chat_id", messageObject.getChatId()); + } else { + args.putInt("chat_id", -messageObject.getFromChatId()); + } + presentFragment(new StatisticActivity(args)); + } + } + }); + + avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle), Theme.getColor(Theme.key_player_actionBarSubtitle)); + avatarContainer.getSubtitleTextView().setLinkTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); + actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + + avatarContainer.setOnClickListener(view -> { + if (getParentLayout().fragmentsStack.size() > 1) { + BaseFragment previousFragemnt = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); + if (previousFragemnt instanceof ChatActivity && ((ChatActivity) previousFragemnt).getCurrentChat().id == chatId) { + finishFragment(); + return; + } + } + Bundle args = new Bundle(); + args.putInt("chat_id", chatId); + args.putInt("message_id", messageId); + args.putBoolean("need_remove_previous_same_chat_activity", false); + ChatActivity a = new ChatActivity(args); + presentFragment(a); + }); + + updateMenu(); + return fragmentView; + } + + private void updateMenu() { + if (chat != null && chat.can_view_stats) { + ActionBarMenu menu = actionBar.createMenu(); + menu.clearItems(); + ActionBarMenuItem headerItem = menu.addItem(0, R.drawable.ic_ab_other); + headerItem.addSubItem(1, R.drawable.msg_stats, LocaleController.getString("ViewChannelStats", R.string.ViewChannelStats)); + } + } + + private void loadChats(int count) { + if (loading) { + return; + } + loading = true; + if (listViewAdapter != null) { + listViewAdapter.notifyDataSetChanged(); + } + TLRPC.TL_stats_getMessagePublicForwards req = new TLRPC.TL_stats_getMessagePublicForwards(); + req.limit = count; + if (messageObject.messageOwner.fwd_from != null) { + req.msg_id = messageObject.messageOwner.fwd_from.saved_from_msg_id; + req.channel = getMessagesController().getInputChannel(-messageObject.getFromChatId()); + } else { + req.msg_id = messageObject.getId(); + req.channel = getMessagesController().getInputChannel((int) -messageObject.getDialogId()); + } + if (!messages.isEmpty()) { + TLRPC.Message message = messages.get(messages.size() - 1); + req.offset_id = message.id; + req.offset_peer = getMessagesController().getInputPeer((int) MessageObject.getDialogId(message)); + req.offset_rate = nextRate; + } else { + req.offset_peer = new TLRPC.TL_inputPeerEmpty(); + } + int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + if ((res.flags & 1) != 0) { + nextRate = res.next_rate; + } + if (res.count != 0) { + publicChats = res.count; + } else if (publicChats == 0) { + publicChats = res.messages.size(); + } + endReached = !(res instanceof TLRPC.TL_messages_messagesSlice); + getMessagesController().putChats(res.chats, false); + getMessagesController().putUsers(res.users, false); + messages.addAll(res.messages); + if (emptyView != null) { + emptyView.showTextView(); + } + } + firstLoaded = true; + loading = false; + updateRows(); + }), null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); + getConnectionsManager().bindRequestToGuid(reqId, classGuid); + } + + private void loadStat() { + TLRPC.TL_stats_getMessageStats req = new TLRPC.TL_stats_getMessageStats(); + if (messageObject.messageOwner.fwd_from != null) { + req.msg_id = messageObject.messageOwner.fwd_from.saved_from_msg_id; + req.channel = getMessagesController().getInputChannel(-messageObject.getFromChatId()); + } else { + req.msg_id = messageObject.getId(); + req.channel = getMessagesController().getInputChannel((int) -messageObject.getDialogId()); + } + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + statsLoaded = true; + if (error != null) { + updateRows(); + return; + } + TLRPC.TL_stats_messageStats res = (TLRPC.TL_stats_messageStats) response; + interactionsViewData = StatisticActivity.createViewData(res.views_graph, LocaleController.getString("InteractionsChartTitle", R.string.InteractionsChartTitle), 1, false); + if (interactionsViewData != null && interactionsViewData.chartData.x.length <= 5) { + statsLoaded = false; + TLRPC.TL_stats_loadAsyncGraph request = new TLRPC.TL_stats_loadAsyncGraph(); + request.token = interactionsViewData.zoomToken; + request.x = interactionsViewData.chartData.x[interactionsViewData.chartData.x.length - 1]; + request.flags |= 1; + + final String cacheKey = interactionsViewData.zoomToken + "_" + request.x; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response1, error1) -> { + ChartData childData = null; + if (response1 instanceof TLRPC.TL_statsGraph) { + String json = ((TLRPC.TL_statsGraph) response1).json.data; + try { + childData = StatisticActivity.createChartData(new JSONObject(json), 1, false); + } catch (JSONException e) { + e.printStackTrace(); + } + } else if (response1 instanceof TLRPC.TL_statsGraphError) { + Toast.makeText(getParentActivity(), ((TLRPC.TL_statsGraphError) response1).error, Toast.LENGTH_LONG).show(); + } + + ChartData finalChildData = childData; + AndroidUtilities.runOnUIThread(() -> { + statsLoaded = true; + if (error1 != null || finalChildData == null) { + updateRows(); + return; + } + childDataCache.put(cacheKey, finalChildData); + interactionsViewData.childChartData = finalChildData; + interactionsViewData.activeZoom = request.x; + updateRows(); + }); + }, null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); + ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); + } else { + updateRows(); + } + }), null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); + } + + @Override + public void onResume() { + super.onResume(); + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + if (listViewAdapter != null) { + listViewAdapter.notifyDataSetChanged(); + } + } + + private class ListAdapter extends RecyclerListView.SelectionAdapter { + + private Context mContext; + + public ListAdapter(Context context) { + mContext = context; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + int type = holder.getItemViewType(); + if (type == 0) { + ManageChatUserCell cell = (ManageChatUserCell) holder.itemView; + return cell.getCurrentObject() instanceof TLObject; + } + return false; + } + + @Override + public int getItemCount() { + return rowCount; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + view = new ManageChatUserCell(mContext, 6, 2, false); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case 1: + view = new ShadowSectionCell(mContext); + break; + case 2: + HeaderCell headerCell = new HeaderCell(mContext, Theme.key_windowBackgroundWhiteBlueHeader, 16, 11, false); + headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + headerCell.setHeight(43); + view = headerCell; + break; + case 4: + view = new StatisticActivity.BaseChartCell(mContext, 1, sharedUi = new BaseChartView.SharedUiComponents()) { + + @Override + public void onZoomed() { + if (data.activeZoom > 0) { + return; + } + performClick(); + if (!chartView.legendSignatureView.canGoZoom) { + return; + } + final long x = chartView.getSelectedDate(); + if (chartType == 4) { + data.childChartData = new StackLinearChartData(data.chartData, x); + zoomChart(false); + return; + } + + if (data.zoomToken == null) { + return; + } + + zoomCanceled(); + final String cacheKey = data.zoomToken + "_" + x; + ChartData dataFromCache = childDataCache.get(cacheKey); + if (dataFromCache != null) { + data.childChartData = dataFromCache; + zoomChart(false); + return; + } + + TLRPC.TL_stats_loadAsyncGraph request = new TLRPC.TL_stats_loadAsyncGraph(); + request.token = data.zoomToken; + if (x != 0) { + request.x = x; + request.flags |= 1; + } + StatisticActivity.ZoomCancelable finalCancelabel; + lastCancelable = finalCancelabel = new StatisticActivity.ZoomCancelable(); + finalCancelabel.adapterPosition = listView.getChildAdapterPosition(this); + + chartView.legendSignatureView.showProgress(true, false); + + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + ChartData childData = null; + if (response instanceof TLRPC.TL_statsGraph) { + String json = ((TLRPC.TL_statsGraph) response).json.data; + try { + childData = StatisticActivity.createChartData(new JSONObject(json), data.graphType, false); + } catch (JSONException e) { + e.printStackTrace(); + } + } else if (response instanceof TLRPC.TL_statsGraphError) { + Toast.makeText(getContext(), ((TLRPC.TL_statsGraphError) response).error, Toast.LENGTH_LONG).show(); + } + + ChartData finalChildData = childData; + AndroidUtilities.runOnUIThread(() -> { + if (finalChildData != null) { + childDataCache.put(cacheKey, finalChildData); + } + if (finalChildData != null && !finalCancelabel.canceled && finalCancelabel.adapterPosition >= 0) { + View view = layoutManager.findViewByPosition(finalCancelabel.adapterPosition); + if (view instanceof StatisticActivity.BaseChartCell) { + data.childChartData = finalChildData; + ((StatisticActivity.BaseChartCell) view).chartView.legendSignatureView.showProgress(false, false); + ((StatisticActivity.BaseChartCell) view).zoomChart(false); + } + } + zoomCanceled(); + }); + }, null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); + ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); + } + + @Override + public void zoomCanceled() { + if (lastCancelable != null) { + lastCancelable.canceled = true; + } + int n = listView.getChildCount(); + for (int i = 0; i < n; i++) { + View child = listView.getChildAt(i); + if (child instanceof StatisticActivity.BaseChartCell) { + ((StatisticActivity.BaseChartCell) child).chartView.legendSignatureView.showProgress(false, true); + } + } + } + + @Override + void loadData(StatisticActivity.ChartViewData viewData) { + // viewData.load(currentAccount, classGuid, ); + } + }; + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case 5: + view = new OverviewCell(mContext); + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case 6: + view = new EmptyCell(mContext, 16); + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 16)); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case 3: + default: + view = new LoadingCell(mContext, AndroidUtilities.dp(40), AndroidUtilities.dp(120)); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: + ManageChatUserCell userCell = (ManageChatUserCell) holder.itemView; + TLRPC.Message item = getItem(position); + int did = (int) MessageObject.getDialogId(item); + TLObject object; + String status = null; + if (did > 0) { + object = getMessagesController().getUser(did); + } else { + object = getMessagesController().getChat(-did); + TLRPC.Chat chat = (TLRPC.Chat) object; + if (chat.participants_count != 0) { + if (ChatObject.isChannel(chat) && !chat.megagroup) { + status = LocaleController.formatPluralString("Subscribers", chat.participants_count); + } else { + status = LocaleController.formatPluralString("Members", chat.participants_count); + } + status = String.format("%1$s, %2$s", status, LocaleController.formatPluralString("Views", item.views)); + } + } + if (object != null) { + userCell.setData(object, null, status, position != endRow - 1); + } + break; + case 1: + holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + break; + case 2: + HeaderCell headerCell = (HeaderCell) holder.itemView; + if (position == overviewHeaderRow) { + headerCell.setText(LocaleController.formatString("StatisticOverview", R.string.StatisticOverview)); + } else { + headerCell.setText(LocaleController.formatPluralString("PublicSharesCount", publicChats)); + } + break; + case 4: + StatisticActivity.BaseChartCell chartCell = (StatisticActivity.BaseChartCell) holder.itemView; + chartCell.updateData(interactionsViewData, false); + chartCell.setLayoutParams(new RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + break; + case 5: + OverviewCell overviewCell = (OverviewCell) holder.itemView; + overviewCell.setData(); + break; + } + } + + @Override + public void onViewRecycled(RecyclerView.ViewHolder holder) { + if (holder.itemView instanceof ManageChatUserCell) { + ((ManageChatUserCell) holder.itemView).recycle(); + } + } + + @Override + public int getItemViewType(int position) { + if (shadowDivideCells.contains(position)) { + return 1; + } else if (position == headerRow || position == overviewHeaderRow) { + return 2; + } else if (position == loadingRow) { + return 3; + } else if (position == interactionsChartRow) { + return 4; + } else if (position == overviewRow) { + return 5; + } else if (position == emptyRow) { + return 6; + } + return 0; + } + + public TLRPC.Message getItem(int position) { + if (position >= startRow && position < endRow) { + return messages.get(position - startRow); + } + return null; + } + } + + public class OverviewCell extends LinearLayout { + + TextView[] primary = new TextView[3]; + TextView[] title = new TextView[3]; + View[] cell = new View[3]; + + public OverviewCell(Context context) { + super(context); + setOrientation(VERTICAL); + setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(HORIZONTAL); + + for (int j = 0; j < 3; j++) { + LinearLayout contentCell = new LinearLayout(context); + cell[j] = contentCell; + contentCell.setOrientation(VERTICAL); + + primary[j] = new TextView(context); + title[j] = new TextView(context); + + primary[j].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + primary[j].setTextSize(17); + title[j].setTextSize(13); + + contentCell.addView(primary[j]); + contentCell.addView(title[j]); + linearLayout.addView(contentCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f)); + } + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + + public void setData() { + primary[0].setText(AndroidUtilities.formatWholeNumber(messageObject.messageOwner.views, 0)); + title[0].setText(LocaleController.getString("StatisticViews", R.string.StatisticViews)); + + if (publicChats > 0) { + cell[1].setVisibility(View.VISIBLE); + primary[1].setText(AndroidUtilities.formatWholeNumber(publicChats, 0)); + title[1].setText(LocaleController.formatString("PublicShares", R.string.PublicShares)); + } else { + cell[1].setVisibility(View.GONE); + } + + int privateChats = messageObject.messageOwner.forwards - publicChats; + if (privateChats > 0) { + cell[2].setVisibility(View.VISIBLE); + primary[2].setText(AndroidUtilities.formatWholeNumber(privateChats, 0)); + title[2].setText(LocaleController.formatString("PrivateShares", R.string.PrivateShares)); + } else { + cell[2].setVisibility(View.GONE); + } + + updateColors(); + } + + private void updateColors() { + for (int i = 0; i < 3; i++) { + primary[i].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + title[i].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + } + } + } + + @Override + public ArrayList getThemeDescriptions() { + ArrayList themeDescriptions = new ArrayList<>(); + + ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { + if (listView != null) { + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + recolorRecyclerItem(listView.getChildAt(a)); + } + count = listView.getHiddenChildCount(); + for (int a = 0; a < count; a++) { + recolorRecyclerItem(listView.getHiddenChildAt(a)); + } + count = listView.getCachedChildCount(); + for (int a = 0; a < count; a++) { + recolorRecyclerItem(listView.getCachedChildAt(a)); + } + count = listView.getAttachedScrapChildCount(); + for (int a = 0; a < count; a++) { + recolorRecyclerItem(listView.getAttachedScrapChildAt(a)); + } + listView.getRecycledViewPool().clear(); + } + if (sharedUi != null) { + sharedUi.invalidate(); + } + + avatarContainer.getSubtitleTextView().setLinkTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + }; + + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, ManageChatUserCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray)); + themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_player_actionBarTitle)); + themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getSubtitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_player_actionBarSubtitle, null)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_statisticChartLineEmpty)); + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); + + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider)); + + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); + + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); + + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue)); + themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink)); + + themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground)); + themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem)); + themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon)); + + StatisticActivity.putColorFromData(interactionsViewData, themeDescriptions, cellDelegate); + return themeDescriptions; + } + + private void recolorRecyclerItem(View child) { + if (child instanceof ManageChatUserCell) { + ((ManageChatUserCell) child).update(0); + } else if (child instanceof StatisticActivity.BaseChartCell) { + ((StatisticActivity.BaseChartCell) child).recolor(); + child.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } else if (child instanceof ShadowSectionCell) { + Drawable shadowDrawable = Theme.getThemedDrawable(ApplicationLoader.applicationContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow); + Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + child.setBackground(combinedDrawable); + } else if (child instanceof ChartHeaderView) { + ((ChartHeaderView) child).recolor(); + } else if (child instanceof OverviewCell) { + ((OverviewCell) child).updateColors(); + child.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } + if (child instanceof EmptyCell) { + child.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index aacccf380..930c36250 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -14,6 +14,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; @@ -43,6 +44,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.WindowManager; +import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.webkit.CookieManager; import android.webkit.JavascriptInterface; @@ -51,19 +53,33 @@ import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; -import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.wallet.AutoResolveHelper; +import com.google.android.gms.wallet.IsReadyToPayRequest; +import com.google.android.gms.wallet.PaymentData; +import com.google.android.gms.wallet.PaymentDataRequest; +import com.google.android.gms.wallet.PaymentsClient; +import com.google.android.gms.wallet.Wallet; +import com.google.android.gms.wallet.WalletConstants; import com.stripe.android.Stripe; import com.stripe.android.TokenCallback; import com.stripe.android.exception.APIConnectionException; import com.stripe.android.exception.APIException; import com.stripe.android.model.Card; import com.stripe.android.model.Token; +import com.stripe.android.net.StripeApiHandler; +import com.stripe.android.net.TokenParser; +import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; @@ -109,10 +125,13 @@ import org.telegram.ui.Components.LayoutHelper; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Optional; public class PaymentFormActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -150,7 +169,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private HashMap codesMap = new HashMap<>(); private HashMap phoneFormatMap = new HashMap<>(); - private GoogleApiClient googleApiClient; + private PaymentsClient paymentsClient; private EditTextBoldCursor[] inputFields; private RadioCell[] radioCells; @@ -173,6 +192,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private TextInfoPrivacyCell[] bottomCell = new TextInfoPrivacyCell[3]; private TextSettingsCell[] settingsCell = new TextSettingsCell[2]; private FrameLayout androidPayContainer; + private FrameLayout googlePayButton; private LinearLayout linearLayout2; private EditTextSettingsCell codeFieldCell; @@ -231,9 +251,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private final static int done_button = 1; - private static final int LOAD_MASKED_WALLET_REQUEST_CODE = 1000; - private static final int LOAD_FULL_WALLET_REQUEST_CODE = 1001; - private final static int fragment_container_id = 4000; + private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 991; private interface PaymentFormActivityDelegate { boolean didSelectNewCard(String tokenJson, String card, boolean saveCard, TLRPC.TL_inputPaymentCredentialsAndroidPay androidPay); @@ -393,16 +411,6 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen FileLog.e(e); } } - if (googleApiClient != null) { - googleApiClient.connect(); - } - } - - @Override - public void onPause() { - if (googleApiClient != null) { - googleApiClient.disconnect(); - } } @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) @@ -991,10 +999,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (androidPayPublicKey != null) { initAndroidPay(context); } - androidPayContainer = new FrameLayout(context); - androidPayContainer.setId(fragment_container_id); - androidPayContainer.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - androidPayContainer.setVisibility(View.GONE); + createAndroidPayButton(context); linearLayout2.addView(androidPayContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); webviewLoading = true; @@ -1093,7 +1098,9 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } } - initAndroidPay(context); + if (!TextUtils.isEmpty(stripeApiKey)) { + initAndroidPay(context); + } inputFields = new EditTextBoldCursor[FIELDS_COUNT_CARD]; for (int a = 0; a < FIELDS_COUNT_CARD; a++) { @@ -1493,10 +1500,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen updateSavePaymentField(); linearLayout2.addView(bottomCell[0], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } else if (a == FIELD_CARD) { - androidPayContainer = new FrameLayout(context); - androidPayContainer.setId(fragment_container_id); - androidPayContainer.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - androidPayContainer.setVisibility(View.GONE); + createAndroidPayButton(context); container.addView(androidPayContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 4, 0)); } @@ -2046,6 +2050,100 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen return fragmentView; } + private void createAndroidPayButton(Context context) { + androidPayContainer = new FrameLayout(context); + androidPayContainer.setBackgroundDrawable(Theme.getSelectorDrawable(true)); + androidPayContainer.setVisibility(View.GONE); + + googlePayButton = new FrameLayout(context); + googlePayButton.setClickable(true); + googlePayButton.setFocusable(true); + googlePayButton.setBackgroundResource(R.drawable.googlepay_button_no_shadow_background); + if (androidPayPublicKey == null) { + googlePayButton.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(2)); + } else { + googlePayButton.setPadding(AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + } + androidPayContainer.addView(googlePayButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + googlePayButton.setOnClickListener(v -> { + googlePayButton.setClickable(false); + try { + JSONObject paymentDataRequest = getBaseRequest(); + + JSONObject cardPaymentMethod = getBaseCardPaymentMethod(); + if (androidPayPublicKey != null) { + cardPaymentMethod.put("tokenizationSpecification", new JSONObject() {{ + put("type", "DIRECT"); + put("parameters", new JSONObject() {{ + put("protocolVersion", "ECv2"); + put("publicKey", androidPayPublicKey); + }}); + }}); + } else { + cardPaymentMethod.put("tokenizationSpecification", new JSONObject() {{ + put("type", "PAYMENT_GATEWAY"); + put("parameters", new JSONObject() {{ + put("gateway", "stripe"); + put("stripe:publishableKey", stripeApiKey); + put("stripe:version", StripeApiHandler.VERSION); + }}); + }}); + } + + paymentDataRequest.put("allowedPaymentMethods", new JSONArray().put(cardPaymentMethod)); + + JSONObject transactionInfo = new JSONObject(); + ArrayList arrayList = new ArrayList<>(paymentForm.invoice.prices); + if (shippingOption != null) { + arrayList.addAll(shippingOption.prices); + } + transactionInfo.put("totalPrice", totalPriceDecimal = getTotalPriceDecimalString(arrayList)); + transactionInfo.put("totalPriceStatus", "FINAL"); + transactionInfo.put("countryCode", countryName); + transactionInfo.put("currencyCode", paymentForm.invoice.currency); + transactionInfo.put("checkoutOption", "COMPLETE_IMMEDIATE_PURCHASE"); + paymentDataRequest.put("transactionInfo", transactionInfo); + + paymentDataRequest.put("merchantInfo", new JSONObject().put("merchantName", currentBotName)); + + /*paymentDataRequest.put("shippingAddressRequired", true); + + JSONObject shippingAddressParameters = new JSONObject(); + shippingAddressParameters.put("phoneNumberRequired", false); + + JSONArray allowedCountryCodes = new JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES); + shippingAddressParameters.put("allowedCountryCodes", allowedCountryCodes); + paymentDataRequest.put("shippingAddressParameters", shippingAddressParameters);*/ + + PaymentDataRequest request = PaymentDataRequest.fromJson(paymentDataRequest.toString()); + if (request != null) { + AutoResolveHelper.resolveTask(paymentsClient.loadPaymentData(request), getParentActivity(), LOAD_PAYMENT_DATA_REQUEST_CODE); + } + } catch (JSONException e) { + throw new RuntimeException("The price cannot be deserialized from the JSON object."); + } + }); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setWeightSum(2); + linearLayout.setGravity(Gravity.CENTER_VERTICAL); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setDuplicateParentStateEnabled(true); + googlePayButton.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + ImageView imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setDuplicateParentStateEnabled(true); + imageView.setImageResource(R.drawable.buy_with_googlepay_button_content); + linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1.0f)); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_XY); + imageView.setDuplicateParentStateEnabled(true); + imageView.setImageResource(R.drawable.googlepay_button_overlay); + googlePayButton.addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } + private void updatePasswordFields() { if (currentStep != 6 || bottomCell[2] == null) { return; @@ -2162,43 +2260,88 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen showDialog(builder.create()); } + private JSONObject getBaseRequest() throws JSONException { + return new JSONObject().put("apiVersion", 2).put("apiVersionMinor", 0); + } + + private JSONObject getBaseCardPaymentMethod() throws JSONException { + List SUPPORTED_NETWORKS = Arrays.asList( + "AMEX", + "DISCOVER", + "JCB", + "MASTERCARD", + "VISA"); + + List SUPPORTED_METHODS = Arrays.asList( + "PAN_ONLY", + "CRYPTOGRAM_3DS"); + + JSONObject cardPaymentMethod = new JSONObject(); + cardPaymentMethod.put("type", "CARD"); + + JSONObject parameters = new JSONObject(); + parameters.put("allowedAuthMethods", new JSONArray(SUPPORTED_METHODS)); + parameters.put("allowedCardNetworks", new JSONArray(SUPPORTED_NETWORKS)); + + // Optionally, you can add billing address/phone number associated with a CARD payment method. + /*parameters.put("billingAddressRequired", true); + + JSONObject billingAddressParameters = new JSONObject(); + billingAddressParameters.put("format", "FULL"); + parameters.put("billingAddressParameters", billingAddressParameters);*/ + + cardPaymentMethod.put("parameters", parameters); + + return cardPaymentMethod; + } + + public Optional getIsReadyToPayRequest() { + try { + JSONObject isReadyToPayRequest = getBaseRequest(); + isReadyToPayRequest.put( + "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod())); + + return Optional.of(isReadyToPayRequest); + } catch (JSONException e) { + return Optional.empty(); + } + } + private void initAndroidPay(Context context) { - /*if (Build.VERSION.SDK_INT < 19) { + if (Build.VERSION.SDK_INT < 19 || getParentActivity() == null) { return; } - googleApiClient = new GoogleApiClient.Builder(context) - .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { - @Override - public void onConnected(Bundle bundle) { - - } - - @Override - public void onConnectionSuspended(int i) { - - } - }) - .addOnConnectionFailedListener(connectionResult -> { - - }) - .addApi(Wallet.API, new Wallet.WalletOptions.Builder() - .setEnvironment(paymentForm.invoice.test ? WalletConstants.ENVIRONMENT_TEST : WalletConstants.ENVIRONMENT_PRODUCTION) - .setTheme(WalletConstants.THEME_LIGHT) - .build()) + Wallet.WalletOptions walletOptions = new Wallet.WalletOptions.Builder() + .setEnvironment(paymentForm.invoice.test ? WalletConstants.ENVIRONMENT_TEST : WalletConstants.ENVIRONMENT_PRODUCTION) + .setTheme(WalletConstants.THEME_LIGHT) .build(); + paymentsClient = Wallet.getPaymentsClient(context, walletOptions); - Wallet.Payments.isReadyToPay(googleApiClient).setResultCallback( - booleanResult -> { - if (booleanResult.getStatus().isSuccess()) { - if (booleanResult.getValue()) { - showAndroidPay(); + final Optional isReadyToPayJson = getIsReadyToPayRequest(); + if (!isReadyToPayJson.isPresent()) { + return; + } + IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString()); + if (request == null) { + return; + } + + Task task = paymentsClient.isReadyToPay(request); + task.addOnCompleteListener(getParentActivity(), + (OnCompleteListener) task1 -> { + if (task1.isSuccessful()) { + if (androidPayContainer != null) { + androidPayContainer.setVisibility(View.VISIBLE); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(ObjectAnimator.ofFloat(androidPayContainer, View.ALPHA, 0.0f, 1.0f)); + animatorSet.setInterpolator(new DecelerateInterpolator()); + animatorSet.setDuration(180); + animatorSet.start(); } } else { - + FileLog.e("isReadyToPay failed", task1.getException()); } - } - ); - googleApiClient.connect();*/ + }); } private String getTotalPriceString(ArrayList prices) { @@ -2300,147 +2443,54 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } } - private void showAndroidPay() { - /*if (getParentActivity() == null || androidPayContainer == null) { - return; - } - - WalletFragmentOptions.Builder optionsBuilder = WalletFragmentOptions.newBuilder(); - optionsBuilder.setEnvironment(paymentForm.invoice.test ? WalletConstants.ENVIRONMENT_TEST : WalletConstants.ENVIRONMENT_PRODUCTION); - optionsBuilder.setMode(WalletFragmentMode.BUY_BUTTON); - - WalletFragmentStyle walletFragmentStyle; - if (androidPayPublicKey != null) { - androidPayContainer.setBackgroundColor(androidPayBackgroundColor); - walletFragmentStyle = new WalletFragmentStyle() - .setBuyButtonText(WalletFragmentStyle.BuyButtonText.BUY_WITH) - .setBuyButtonAppearance(androidPayBlackTheme ? WalletFragmentStyle.BuyButtonAppearance.ANDROID_PAY_LIGHT_WITH_BORDER : WalletFragmentStyle.BuyButtonAppearance.ANDROID_PAY_DARK) - .setBuyButtonWidth(WalletFragmentStyle.Dimension.MATCH_PARENT); - } else { - walletFragmentStyle = new WalletFragmentStyle() - .setBuyButtonText(WalletFragmentStyle.BuyButtonText.LOGO_ONLY) - .setBuyButtonAppearance(WalletFragmentStyle.BuyButtonAppearance.ANDROID_PAY_LIGHT_WITH_BORDER) - .setBuyButtonWidth(WalletFragmentStyle.Dimension.WRAP_CONTENT); - } - - optionsBuilder.setFragmentStyle(walletFragmentStyle); - WalletFragment walletFragment = WalletFragment.newInstance(optionsBuilder.build()); - FragmentManager fragmentManager = getParentActivity().getFragmentManager(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(fragment_container_id, walletFragment); - fragmentTransaction.commit(); - - ArrayList arrayList = new ArrayList<>(paymentForm.invoice.prices); - if (shippingOption != null) { - arrayList.addAll(shippingOption.prices); - } - totalPriceDecimal = getTotalPriceDecimalString(arrayList); - - PaymentMethodTokenizationParameters parameters; - if (androidPayPublicKey != null) { - parameters = PaymentMethodTokenizationParameters.newBuilder() - .setPaymentMethodTokenizationType(PaymentMethodTokenizationType.NETWORK_TOKEN) - .addParameter("publicKey", androidPayPublicKey) - .build(); - } else { - parameters = PaymentMethodTokenizationParameters.newBuilder() - .setPaymentMethodTokenizationType(PaymentMethodTokenizationType.PAYMENT_GATEWAY) - .addParameter("gateway", "stripe") - .addParameter("stripe:publishableKey", stripeApiKey) - .addParameter("stripe:version", StripeApiHandler.VERSION) - .build(); - } - - MaskedWalletRequest maskedWalletRequest = MaskedWalletRequest.newBuilder() - .setPaymentMethodTokenizationParameters(parameters) - .setEstimatedTotalPrice(totalPriceDecimal) - .setCurrencyCode(paymentForm.invoice.currency) - .build(); - - WalletFragmentInitParams initParams = WalletFragmentInitParams.newBuilder() - .setMaskedWalletRequest(maskedWalletRequest) - .setMaskedWalletRequestCode(LOAD_MASKED_WALLET_REQUEST_CODE) - .build(); - - walletFragment.initialize(initParams); - androidPayContainer.setVisibility(View.VISIBLE); - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(androidPayContainer, "alpha", 0.0f, 1.0f)); - animatorSet.setInterpolator(new DecelerateInterpolator()); - animatorSet.setDuration(180); - animatorSet.start();*/ - } - @Override public void onActivityResultFragment(int requestCode, int resultCode, Intent data) { - /*if (requestCode == LOAD_MASKED_WALLET_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - showEditDoneProgress(true, true); - setDonePressed(true); - - MaskedWallet maskedWallet = data.getParcelableExtra(WalletConstants.EXTRA_MASKED_WALLET); - - Cart.Builder cardBuilder = Cart.newBuilder() - .setCurrencyCode(paymentForm.invoice.currency) - .setTotalPrice(totalPriceDecimal); - - ArrayList arrayList = new ArrayList<>(paymentForm.invoice.prices); - if (shippingOption != null) { - arrayList.addAll(shippingOption.prices); - } - for (int a = 0; a < arrayList.size(); a++) { - TLRPC.TL_labeledPrice price = arrayList.get(a); - String amount = LocaleController.getInstance().formatCurrencyDecimalString(price.amount, paymentForm.invoice.currency, false); - cardBuilder.addLineItem(LineItem.newBuilder() - .setCurrencyCode(paymentForm.invoice.currency) - .setQuantity("1") - .setDescription(price.label) - .setTotalPrice(amount) - .setUnitPrice(amount).build()); - } - FullWalletRequest fullWalletRequest = FullWalletRequest.newBuilder() - .setCart(cardBuilder.build()) - .setGoogleTransactionId(maskedWallet.getGoogleTransactionId()) - .build(); - Wallet.Payments.loadFullWallet(googleApiClient, fullWalletRequest, LOAD_FULL_WALLET_REQUEST_CODE); - } else { - showEditDoneProgress(true, false); - setDonePressed(false); - } - } else if (requestCode == LOAD_FULL_WALLET_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - FullWallet fullWallet = data.getParcelableExtra(WalletConstants.EXTRA_FULL_WALLET); - String tokenJSON = fullWallet.getPaymentMethodToken().getToken(); - try { - if (androidPayPublicKey != null) { - androidPayCredentials = new TLRPC.TL_inputPaymentCredentialsAndroidPay(); - androidPayCredentials.payment_token = new TLRPC.TL_dataJSON(); - androidPayCredentials.payment_token.data = tokenJSON; - androidPayCredentials.google_transaction_id = fullWallet.getGoogleTransactionId(); - String[] descriptions = fullWallet.getPaymentDescriptions(); - if (descriptions.length > 0) { - cardName = descriptions[0]; - } else { - cardName = "Android Pay"; - } - } else { - Token token = TokenParser.parseToken(tokenJSON); - paymentJson = String.format(Locale.US, "{\"type\":\"%1$s\", \"id\":\"%2$s\"}", token.getType(), token.getId()); - Card card = token.getCard(); - cardName = card.getType() + " *" + card.getLast4(); + if (requestCode == LOAD_PAYMENT_DATA_REQUEST_CODE) { + AndroidUtilities.runOnUIThread(() -> { + if (resultCode == Activity.RESULT_OK) { + PaymentData paymentData = PaymentData.getFromIntent(data); + final String paymentInfo = paymentData.toJson(); + if (paymentInfo == null) { + return; + } + try { + JSONObject paymentMethodData = new JSONObject(paymentInfo).getJSONObject("paymentMethodData"); + final JSONObject tokenizationData = paymentMethodData.getJSONObject("tokenizationData"); + final String tokenizationType = tokenizationData.getString("type"); + final String token = tokenizationData.getString("token"); + + if (androidPayPublicKey != null) { + androidPayCredentials = new TLRPC.TL_inputPaymentCredentialsAndroidPay(); + androidPayCredentials.payment_token = new TLRPC.TL_dataJSON(); + androidPayCredentials.payment_token.data = tokenizationData.toString(); + androidPayCredentials.google_transaction_id = ""; + String descriptions = paymentMethodData.optString("description"); + if (!TextUtils.isEmpty(descriptions)) { + cardName = descriptions; + } else { + cardName = "Android Pay"; + } + } else { + Token t = TokenParser.parseToken(token); + paymentJson = String.format(Locale.US, "{\"type\":\"%1$s\", \"id\":\"%2$s\"}", t.getType(), t.getId()); + Card card = t.getCard(); + cardName = card.getType() + " *" + card.getLast4(); + } + goToNextStep(); + } catch (JSONException e) { + throw new RuntimeException("The selected garment cannot be parsed from the list of elements"); + } + } else { + if (resultCode == AutoResolveHelper.RESULT_ERROR) { + Status status = AutoResolveHelper.getStatusFromIntent(data); + FileLog.e("android pay error " + status.getStatusMessage()); } - goToNextStep(); - showEditDoneProgress(true, false); - setDonePressed(false); - } catch (JSONException ignore) { - showEditDoneProgress(true, false); - setDonePressed(false); } - } else { showEditDoneProgress(true, false); setDonePressed(false); - } - }*/ + googlePayButton.setClickable(true); + }); + } } private void goToNextStep() { @@ -3181,30 +3231,29 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen progressView.setVisibility(View.VISIBLE); doneItem.setEnabled(false); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 0.0f), - ObjectAnimator.ofFloat(progressView, "scaleX", 1.0f), - ObjectAnimator.ofFloat(progressView, "scaleY", 1.0f), - ObjectAnimator.ofFloat(progressView, "alpha", 1.0f)); + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(progressView, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(progressView, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(progressView, View.ALPHA, 1.0f)); } else { if (webView != null) { doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(progressView, "scaleX", 0.1f), - ObjectAnimator.ofFloat(progressView, "scaleY", 0.1f), - ObjectAnimator.ofFloat(progressView, "alpha", 0.0f)); + ObjectAnimator.ofFloat(progressView, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(progressView, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(progressView, View.ALPHA, 0.0f)); } else { doneItem.getContentView().setVisibility(View.VISIBLE); doneItem.setEnabled(true); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(progressView, "scaleX", 0.1f), - ObjectAnimator.ofFloat(progressView, "scaleY", 0.1f), - ObjectAnimator.ofFloat(progressView, "alpha", 0.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 1.0f)); + ObjectAnimator.ofFloat(progressView, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(progressView, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(progressView, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.ALPHA, 1.0f)); } - } doneItemAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -3233,22 +3282,22 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen progressViewButton.setVisibility(View.VISIBLE); bottomLayout.setEnabled(false); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(payTextView, "scaleX", 0.1f), - ObjectAnimator.ofFloat(payTextView, "scaleY", 0.1f), - ObjectAnimator.ofFloat(payTextView, "alpha", 0.0f), - ObjectAnimator.ofFloat(progressViewButton, "scaleX", 1.0f), - ObjectAnimator.ofFloat(progressViewButton, "scaleY", 1.0f), - ObjectAnimator.ofFloat(progressViewButton, "alpha", 1.0f)); + ObjectAnimator.ofFloat(payTextView, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(payTextView, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(payTextView, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(progressViewButton, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(progressViewButton, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(progressViewButton, View.ALPHA, 1.0f)); } else { payTextView.setVisibility(View.VISIBLE); bottomLayout.setEnabled(true); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(progressViewButton, "scaleX", 0.1f), - ObjectAnimator.ofFloat(progressViewButton, "scaleY", 0.1f), - ObjectAnimator.ofFloat(progressViewButton, "alpha", 0.0f), - ObjectAnimator.ofFloat(payTextView, "scaleX", 1.0f), - ObjectAnimator.ofFloat(payTextView, "scaleY", 1.0f), - ObjectAnimator.ofFloat(payTextView, "alpha", 1.0f)); + ObjectAnimator.ofFloat(progressViewButton, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(progressViewButton, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(progressViewButton, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(payTextView, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(payTextView, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(payTextView, View.ALPHA, 1.0f)); } doneItemAnimation.addListener(new AnimatorListenerAdapter() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index a5bdf7d64..c9e330b76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -57,6 +57,7 @@ import androidx.core.widget.NestedScrollView; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; +import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerEnd; @@ -161,6 +162,7 @@ import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -224,6 +226,7 @@ import java.lang.reflect.Method; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -285,7 +288,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ActionBarMenuItem shareItem; private LinearLayout itemsLayout; private Map actionBarItemsVisibility = new HashMap<>(3); + private LinearLayout bottomButtonsLayout; private ImageView shareButton; + private ImageView paintButton; private BackgroundDrawable backgroundDrawable = new BackgroundDrawable(0xff000000); private Paint blackPaint = new Paint(); private CheckBox checkImageView; @@ -452,6 +457,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private long lastBufferedPositionCheck; private View playButtonAccessibilityOverlay; private StickersAlert masksAlert; + private int lastImageId = -1; private int keyboardSize; @@ -836,6 +842,39 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private class SavedState { + + private int index; + private ArrayList messages; + private PhotoViewerProvider provider; + + public SavedState(int index, ArrayList messages, PhotoViewerProvider provider) { + this.messages = messages; + this.index = index; + this.provider = provider; + } + + public void restore() { + placeProvider = provider; + + if (Build.VERSION.SDK_INT >= 21) { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | + WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + windowLayoutParams.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; + windowView.setFocusable(false); + containerView.setFocusable(false); + backgroundDrawable.setAlpha(255); + containerView.setAlpha(1.0f); + + onPhotoShow(null, null, null, null, messages, null, null, index, provider.getPlaceForPhoto(messages.get(index), null, index, true)); + } + } + private int currentImageHasFace; private String currentImageFaceKey; private PaintingOverlay paintingOverlay; @@ -938,6 +977,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ArrayList avatarsArr = new ArrayList<>(); private ArrayList imagesArrLocals = new ArrayList<>(); private ImageLocation currentAvatarLocation = null; + private SavedState savedState = null; private PageBlocksAdapter pageBlocksAdapter; @@ -1674,19 +1714,35 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (photoFilterView != null) { photoFilterView.setTranslationY(y); } - if (photoPaintView != null) { - photoPaintView.setTranslationY(y); - } +// if (pickerView != null) { pickerView.setTranslationY(y); } if (pickerViewSendButton != null) { pickerViewSendButton.setTranslationY(y); } - if (captionEditText != null) { - float p = progress < 0.5f ? 0 : (progress - 0.5f) / 0.5f; - captionEditText.setAlpha(p); - captionEditText.setTranslationY(y - this.keyboardSize + AndroidUtilities.dp(keyboardSize / 2) * (1f - progress)); + + if (currentEditMode == 3) { + if (captionEditText != null) { + captionEditText.setTranslationY(y); + } + + if (photoPaintView != null) { + photoPaintView.setTranslationY(0); + photoPaintView.getColorPicker().setTranslationY(y); + photoPaintView.getToolsView().setTranslationY(y); + photoPaintView.getCurtainView().setTranslationY(y); + } + } else { + + if (photoPaintView != null) { + photoPaintView.setTranslationY(y); + } + if (captionEditText != null) { + float p = progress < 0.5f ? 0 : (progress - 0.5f) / 0.5f; + captionEditText.setAlpha(p); + captionEditText.setTranslationY(y - this.keyboardSize + AndroidUtilities.dp(keyboardSize / 2) * (1f - progress)); + } } if (muteItem != null) { muteItem.setTranslationY(y); @@ -1851,7 +1907,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat protected void onLayout(boolean changed, int _l, int t, int _r, int _b) { final int count = getChildCount(); int keyboardHeight = getKeyboardHeight(); - keyboardSize = SharedConfig.smoothKeyboard ? 0 : keyboardHeight; + keyboardSize = keyboardHeight; int paddingBottom = keyboardHeight <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow ? captionEditText.getEmojiPadding() : 0; for (int i = 0; i < count; i++) { @@ -1968,6 +2024,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return false; } } + if (child == mentionListView) { + canvas.save(); + canvas.clipRect(child.getX(), child.getY(), child.getX() + child.getWidth(), child.getY() + child.getHeight()); + boolean r = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return r; + } } else if (child == cameraItem || child == muteItem || child == pickerView || child == videoTimelineView || child == pickerViewSendButton || child == captionTextViewSwitcher || muteItem.getVisibility() == VISIBLE && child == bottomLayout) { if (captionEditText.isPopupAnimatig()) { child.setTranslationY(captionEditText.getEmojiPadding()); @@ -3217,7 +3280,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (animationInProgress == 3) { blackPaint.setAlpha((int) (255 * (1.0f - animatingImageView.getAnimationProgress()))); } else { - blackPaint.setAlpha(255); + blackPaint.setAlpha(backgroundDrawable.getAlpha()); } canvas.drawRect(0, getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight() + insets.getSystemWindowInsetBottom(), blackPaint); } @@ -3319,7 +3382,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } File f = null; - boolean isVideo = false; + final boolean isVideo; if (currentMessageObject != null) { if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && currentMessageObject.messageOwner.media.webpage != null && currentMessageObject.messageOwner.media.webpage.document == null) { TLObject fileLocation = getFileLocation(currentIndex, null); @@ -3330,14 +3393,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat isVideo = currentMessageObject.isVideo(); } else if (currentFileLocationVideo != null) { f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); + isVideo = false; } else if (pageBlocksAdapter != null) { f = pageBlocksAdapter.getFile(currentIndex); isVideo = pageBlocksAdapter.isVideo(currentIndex); + } else { + isVideo = false; } if (f != null && f.exists()) { - MediaController.saveFile(f.toString(), parentActivity, isVideo ? 1 : 0, null, null); - BulletinFactory.createSaveToGalleryBulletin(containerView, isVideo, 0xf9222222, 0xffffffff).show(); + MediaController.saveFile(f.toString(), parentActivity, isVideo ? 1 : 0, null, null, () -> { + BulletinFactory.createSaveToGalleryBulletin(containerView, isVideo, 0xf9222222, 0xffffffff).show(); + }); } else { showDownloadAlert(); } @@ -3369,7 +3436,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (lower_part != 0) { if (lower_part > 0) { args.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); if (chat != null && chat.migrated_to != null) { args.putInt("migrated_to", lower_part); @@ -3989,11 +4056,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat miniProgressView.setAlpha(0.0f); containerView.addView(miniProgressView, LayoutHelper.createFrame(64, 64, Gravity.CENTER)); + bottomButtonsLayout = new LinearLayout(containerView.getContext()); + bottomButtonsLayout.setOrientation(LinearLayout.HORIZONTAL); + bottomLayout.addView(bottomButtonsLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); + + paintButton = new ImageView(containerView.getContext()); + paintButton.setImageResource(R.drawable.photo_paint); + paintButton.setScaleType(ImageView.ScaleType.CENTER); + paintButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); + bottomButtonsLayout.addView(paintButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT)); + paintButton.setOnClickListener(v -> openCurrentPhotoInPaintModeForSelect()); + paintButton.setContentDescription(LocaleController.getString("AccDescrPhotoEditor", R.string.AccDescrPhotoEditor)); + shareButton = new ImageView(containerView.getContext()); shareButton.setImageResource(R.drawable.share); shareButton.setScaleType(ImageView.ScaleType.CENTER); shareButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); - bottomLayout.addView(shareButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); + bottomButtonsLayout.addView(shareButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT)); shareButton.setOnClickListener(v -> onSharePressed()); shareButton.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); @@ -5519,7 +5598,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }); animatorSet.start(); if (!fromGesture) { - toggleActionBar(false, true, new ActionBarToggleParams().enableStatusBarAnimation(false).animationDuration(250).animationInterpolator(new DecelerateInterpolator())); + toggleActionBar(false, true, new ActionBarToggleParams().enableStatusBarAnimation(false).enableTranslationAnimation(false).animationDuration(250).animationInterpolator(new DecelerateInterpolator())); } } else { switchToInlineRunnable.run(); @@ -6415,7 +6494,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }); animatorSet.start(); - toggleActionBar(true, true, new ActionBarToggleParams().enableStatusBarAnimation(false).animationDuration(250).animationInterpolator(interpolator)); + toggleActionBar(true, true, new ActionBarToggleParams().enableStatusBarAnimation(false).enableTranslationAnimation(false).animationDuration(250).animationInterpolator(interpolator)); } else { toggleActionBar(true, false); //containerView.setTranslationY(0); @@ -6632,7 +6711,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat dateTextView.setVisibility(View.VISIBLE); nameTextView.setVisibility(View.VISIBLE); if (allowShare) { - shareButton.setVisibility(View.VISIBLE); + bottomButtonsLayout.setVisibility(View.VISIBLE); } } final boolean shareWasAllowed = allowShare; @@ -6644,7 +6723,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat dateTextView.setAlpha(1f - alpha); nameTextView.setAlpha(1f - alpha); if (shareWasAllowed) { - shareButton.setAlpha(1f - alpha); + bottomButtonsLayout.setAlpha(1f - alpha); } }); anim.addListener(new AnimatorListenerAdapter() { @@ -6656,7 +6735,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat dateTextView.setVisibility(View.GONE); nameTextView.setVisibility(View.GONE); if (shareWasAllowed) { - shareButton.setVisibility(View.GONE); + bottomButtonsLayout.setVisibility(View.GONE); } } } @@ -6671,8 +6750,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat nameTextView.setVisibility(visible ? View.GONE : View.VISIBLE); nameTextView.setAlpha(visible ? 0f : 1f); if (allowShare) { - shareButton.setVisibility(visible ? View.GONE : View.VISIBLE); - shareButton.setAlpha(visible ? 0f : 1f); + bottomButtonsLayout.setVisibility(visible ? View.GONE : View.VISIBLE); + bottomButtonsLayout.setAlpha(visible ? 0f : 1f); } } if (allowShare && pageBlocksAdapter == null) { @@ -6938,7 +7017,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (croppedPaintBitmap != null) { croppedPaintBitmap.recycle(); } - paintBitmap.recycle(); + if (paintBitmap != null) { + paintBitmap.recycle(); + } } else { if (!isCurrentVideo) { TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); @@ -7480,6 +7561,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat updateMinMax(scale); containerView.invalidate(); + if (savedState != null) { + savedState.restore(); + savedState = null; + final ActionBarToggleParams toggleParams = new ActionBarToggleParams().enableStatusBarAnimation(false); + toggleActionBar(false, false, toggleParams); + toggleActionBar(true, true, toggleParams); + return; + } + AnimatorSet animatorSet = new AnimatorSet(); ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0)); @@ -7824,72 +7914,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat changeModeAnimation.start(); } else if (mode == 3) { startVideoPlayer(); - if (photoPaintView == null) { - int w; - int h; - if (videoTextureView != null) { - VideoEditTextureView textureView = (VideoEditTextureView) videoTextureView; - w = textureView.getVideoWidth(); - h = textureView.getVideoHeight(); - while (w > 1280 || h > 1280) { - w /= 2; - h /= 2; - } - } else { - w = centerImage.getBitmapWidth(); - h = centerImage.getBitmapHeight(); - } - Bitmap bitmap = paintingOverlay.getBitmap(); - if (bitmap == null) { - bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - } - MediaController.CropState state; - if (sendPhotoType == SELECT_TYPE_AVATAR) { - state = new MediaController.CropState(); - state.transformRotation = cropTransform.getOrientation(); - } else { - state = editState.cropState; - } - photoPaintView = new PhotoPaintView(parentActivity, bitmap, isCurrentVideo ? null : centerImage.getBitmap(), centerImage.getOrientation(), editState.mediaEntities, state, () -> paintingOverlay.hideBitmap()) { - @Override - protected void onOpenCloseStickersAlert(boolean open) { - if (videoPlayer == null) { - return; - } - manuallyPaused = false; - cancelVideoPlayRunnable(); - if (open) { - videoPlayer.pause(); - } else { - videoPlayer.play(); - } - } + createPaintView(); - @Override - protected void didSetAnimatedSticker(RLottieDrawable drawable) { - if (videoPlayer == null) { - return; - } - drawable.setProgressMs(videoPlayer.getCurrentPosition() - (startTime > 0 ? startTime / 1000 : 0)); - } - }; - containerView.addView(photoPaintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - photoPaintView.getDoneTextView().setOnClickListener(v -> { - applyCurrentEditMode(); - switchToEditMode(0); - }); - photoPaintView.getCancelTextView().setOnClickListener(v -> photoPaintView.maybeShowDismissalAlert(PhotoViewer.this, parentActivity, () -> switchToEditMode(0))); - photoPaintView.getColorPicker().setTranslationY(AndroidUtilities.dp(126)); - photoPaintView.getToolsView().setTranslationY(AndroidUtilities.dp(126)); - } changeModeAnimation = new AnimatorSet(); ArrayList arrayList = new ArrayList<>(); - arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); - arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); - arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); + arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); + arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); + arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); if (needCaptionLayout) { - arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); + arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); } if (sendPhotoType == 0 || sendPhotoType == 4) { arrayList.add(ObjectAnimator.ofFloat(checkImageView, View.ALPHA, 1, 0)); @@ -7911,98 +7945,168 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat changeModeAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - changeModeAnimation = null; - pickerView.setVisibility(View.GONE); - pickerViewSendButton.setVisibility(View.GONE); - cameraItem.setVisibility(View.GONE); - muteItem.setVisibility(View.GONE); - if (photoCropView != null) { - photoCropView.setVisibility(View.INVISIBLE); - } - selectedPhotosListView.setVisibility(View.GONE); - selectedPhotosListView.setAlpha(0.0f); - selectedPhotosListView.setTranslationY(-AndroidUtilities.dp(10)); - photosCounterView.setRotationX(0.0f); - selectedPhotosListView.setEnabled(false); - isPhotosListViewVisible = false; - if (needCaptionLayout) { - captionTextViewSwitcher.setVisibility(View.INVISIBLE); - } - if (sendPhotoType == 0 || sendPhotoType == 4 || (sendPhotoType == 2 || sendPhotoType == 5) && imagesArrLocals.size() > 1) { - checkImageView.setVisibility(View.GONE); - photosCounterView.setVisibility(View.GONE); - } - - Bitmap bitmap = centerImage.getBitmap(); - if (bitmap != null) { - int bitmapWidth = centerImage.getBitmapWidth(); - int bitmapHeight = centerImage.getBitmapHeight(); - - float oldScale; - float newScale; - if (sendPhotoType == SELECT_TYPE_AVATAR) { - animateToY = AndroidUtilities.dp(12); - if (cropTransform.getOrientation() == 90 || cropTransform.getOrientation() == 270) { - int temp = bitmapWidth; - bitmapWidth = bitmapHeight; - bitmapHeight = temp; - } - } else { - animateToY = -AndroidUtilities.dp(44) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight / 2 : 0); - if (editState.cropState != null) { - if (editState.cropState.transformRotation == 90 || editState.cropState.transformRotation == 270) { - int temp = bitmapWidth; - bitmapWidth = bitmapHeight; - bitmapHeight = temp; - } - bitmapWidth *= editState.cropState.cropPw; - bitmapHeight *= editState.cropState.cropPh; - } - } - oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); - newScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); - animateToScale = newScale / oldScale; - animateToX = getLeftInset() / 2 - getRightInset() / 2; - animationStartTime = System.currentTimeMillis(); - zoomAnimation = true; - } - - imageMoveAnimation = new AnimatorSet(); - imageMoveAnimation.playTogether( - ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1), - ObjectAnimator.ofFloat(photoPaintView.getColorPicker(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0), - ObjectAnimator.ofFloat(photoPaintView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0) - ); - imageMoveAnimation.setDuration(200); - imageMoveAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - photoPaintView.init(); - paintingOverlay.hideEntities(); - imageMoveAnimation = null; - currentEditMode = mode; - switchingToMode = -1; - animateToScale = 1; - animateToX = 0; - animateToY = 0; - scale = 1; - updateMinMax(scale); - padImageForHorizontalInsets = true; - containerView.invalidate(); - } - }); - imageMoveAnimation.start(); + switchToPaintMode(); } }); changeModeAnimation.start(); } } + private void createPaintView() { + if (photoPaintView == null) { + int w; + int h; + if (videoTextureView != null) { + VideoEditTextureView textureView = (VideoEditTextureView) videoTextureView; + w = textureView.getVideoWidth(); + h = textureView.getVideoHeight(); + while (w > 1280 || h > 1280) { + w /= 2; + h /= 2; + } + } else { + w = centerImage.getBitmapWidth(); + h = centerImage.getBitmapHeight(); + } + Bitmap bitmap = paintingOverlay.getBitmap(); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + } + MediaController.CropState state; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + state = new MediaController.CropState(); + state.transformRotation = cropTransform.getOrientation(); + } else { + state = editState.cropState; + } + photoPaintView = new PhotoPaintView(parentActivity, bitmap, isCurrentVideo ? null : centerImage.getBitmap(), centerImage.getOrientation(), editState.mediaEntities, state, () -> paintingOverlay.hideBitmap()) { + @Override + protected void onOpenCloseStickersAlert(boolean open) { + if (videoPlayer == null) { + return; + } + manuallyPaused = false; + cancelVideoPlayRunnable(); + if (open) { + videoPlayer.pause(); + } else { + videoPlayer.play(); + } + } + + @Override + protected void didSetAnimatedSticker(RLottieDrawable drawable) { + if (videoPlayer == null) { + return; + } + drawable.setProgressMs(videoPlayer.getCurrentPosition() - (startTime > 0 ? startTime / 1000 : 0)); + } + }; + containerView.addView(photoPaintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + photoPaintView.getDoneTextView().setOnClickListener(v -> { + savedState = null; + applyCurrentEditMode(); + switchToEditMode(0); + }); + photoPaintView.getCancelTextView().setOnClickListener(v -> closePaintMode()); + photoPaintView.getColorPicker().setTranslationY(AndroidUtilities.dp(126)); + photoPaintView.getToolsView().setTranslationY(AndroidUtilities.dp(126)); + } + } + + private void closePaintMode() { + photoPaintView.maybeShowDismissalAlert(PhotoViewer.this, parentActivity, () -> switchToEditMode(0)); + } + + private void switchToPaintMode() { + changeModeAnimation = null; + pickerView.setVisibility(View.GONE); + pickerViewSendButton.setVisibility(View.GONE); + cameraItem.setVisibility(View.GONE); + muteItem.setVisibility(View.GONE); + if (photoCropView != null) { + photoCropView.setVisibility(View.INVISIBLE); + } + selectedPhotosListView.setVisibility(View.GONE); + selectedPhotosListView.setAlpha(0.0f); + selectedPhotosListView.setTranslationY(-AndroidUtilities.dp(10)); + photosCounterView.setRotationX(0.0f); + selectedPhotosListView.setEnabled(false); + isPhotosListViewVisible = false; + if (needCaptionLayout) { + captionTextViewSwitcher.setVisibility(View.INVISIBLE); + } + if (sendPhotoType == 0 || sendPhotoType == 4 || (sendPhotoType == 2 || sendPhotoType == 5) && imagesArrLocals.size() > 1) { + checkImageView.setVisibility(View.GONE); + photosCounterView.setVisibility(View.GONE); + } + + Bitmap bitmap = centerImage.getBitmap(); + if (bitmap != null) { + int bitmapWidth = centerImage.getBitmapWidth(); + int bitmapHeight = centerImage.getBitmapHeight(); + + float oldScale; + float newScale; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + animateToY = AndroidUtilities.dp(12); + if (cropTransform.getOrientation() == 90 || cropTransform.getOrientation() == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + } + } else { + animateToY = -AndroidUtilities.dp(44) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight / 2 : 0); + if (editState.cropState != null) { + if (editState.cropState.transformRotation == 90 || editState.cropState.transformRotation == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + } + bitmapWidth *= editState.cropState.cropPw; + bitmapHeight *= editState.cropState.cropPh; + } + } + oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); + newScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); + animateToScale = newScale / oldScale; + animateToX = getLeftInset() / 2 - getRightInset() / 2; + animationStartTime = System.currentTimeMillis(); + zoomAnimation = true; + } + + imageMoveAnimation = new AnimatorSet(); + imageMoveAnimation.playTogether( + ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1), + ObjectAnimator.ofFloat(photoPaintView.getColorPicker(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0), + ObjectAnimator.ofFloat(photoPaintView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0) + ); + imageMoveAnimation.setDuration(200); + imageMoveAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + photoPaintView.init(); + paintingOverlay.hideEntities(); + imageMoveAnimation = null; + currentEditMode = 3; + switchingToMode = -1; + animateToScale = 1; + animateToX = 0; + animateToY = 0; + scale = 1; + updateMinMax(scale); + padImageForHorizontalInsets = true; + containerView.invalidate(); + } + }); + imageMoveAnimation.start(); + } + private void toggleCheckImageView(boolean show) { AnimatorSet animatorSet = new AnimatorSet(); ArrayList arrayList = new ArrayList<>(); @@ -8101,6 +8205,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public int animationDuration = 200; public Interpolator animationInterpolator; public boolean enableStatusBarAnimation = true; + public boolean enableTranslationAnimation = true; public ActionBarToggleParams() { } @@ -8110,6 +8215,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return this; } + public ActionBarToggleParams enableTranslationAnimation(boolean val) { + enableTranslationAnimation = val; + return this; + } + public ActionBarToggleParams animationDuration(int val) { animationDuration = val; return this; @@ -8159,20 +8269,20 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat final float offsetY = AndroidUtilities.dpf2(24); - videoPlayerControlFrameLayout.setSeekBarTransitionEnabled(params.enableStatusBarAnimation && playerLooping); - videoPlayerControlFrameLayout.setTranslationYAnimationEnabled(params.enableStatusBarAnimation); + videoPlayerControlFrameLayout.setSeekBarTransitionEnabled(params.enableTranslationAnimation && playerLooping); + videoPlayerControlFrameLayout.setTranslationYAnimationEnabled(params.enableTranslationAnimation); if (animated) { ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.ALPHA, show ? 1.0f : 0.0f)); - if (params.enableStatusBarAnimation) { + if (params.enableTranslationAnimation) { arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, show ? 0 : -offsetY)); } else { actionBar.setTranslationY(0); } if (bottomLayout != null) { arrayList.add(ObjectAnimator.ofFloat(bottomLayout, View.ALPHA, show ? 1.0f : 0.0f)); - if (params.enableStatusBarAnimation) { + if (params.enableTranslationAnimation) { arrayList.add(ObjectAnimator.ofFloat(bottomLayout, View.TRANSLATION_Y, show ? 0 : offsetY)); } else { bottomLayout.setTranslationY(0); @@ -8184,14 +8294,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoPlayerControlFrameLayout.setProgress(show ? 1.0f : 0.0f); } arrayList.add(ObjectAnimator.ofFloat(groupedPhotosListView, View.ALPHA, show ? 1.0f : 0.0f)); - if (params.enableStatusBarAnimation) { + if (params.enableTranslationAnimation) { arrayList.add(ObjectAnimator.ofFloat(groupedPhotosListView, View.TRANSLATION_Y, show ? 0 : offsetY)); } else { groupedPhotosListView.setTranslationY(0); } if (!needCaptionLayout && captionScrollView != null) { arrayList.add(ObjectAnimator.ofFloat(captionScrollView, View.ALPHA, show ? 1.0f : 0.0f)); - if (params.enableStatusBarAnimation) { + if (params.enableTranslationAnimation) { arrayList.add(ObjectAnimator.ofFloat(captionScrollView, View.TRANSLATION_Y, show ? 0 : offsetY)); } else { captionScrollView.setTranslationY(0); @@ -8587,7 +8697,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLocation fileLocation, ImageLocation imageLocation, ImageLocation videoLocation, final ArrayList messages, final ArrayList documents, final ArrayList photos, int index, final PlaceProviderObject object) { + private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLocation fileLocation, ImageLocation imageLocation, ImageLocation videoLocation, final ArrayList messages, final ArrayList documents, final List photos, int index, final PlaceProviderObject object) { classGuid = ConnectionsManager.generateClassGuid(); currentMessageObject = null; currentFileLocation = null; @@ -8656,7 +8766,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat bottomLayout.setTag(1); bottomLayout.setTranslationY(0); captionTextViewSwitcher.setTranslationY(0); - shareButton.setVisibility(View.GONE); + bottomButtonsLayout.setVisibility(View.GONE); + paintButton.setVisibility(View.GONE); if (qualityChooseView != null) { qualityChooseView.setVisibility(View.INVISIBLE); qualityPicker.setVisibility(View.INVISIBLE); @@ -8829,10 +8940,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imagesArrLocationsSizes.add(object != null ? object.size : 0); imagesArrMessages.add(null); avatarsArr.add(new TLRPC.TL_photoEmpty()); - shareButton.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); + bottomButtonsLayout.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); allowShare = true; menuItem.hideSubItem(gallery_menu_showall); - if (shareButton.getVisibility() == View.VISIBLE) { + if (bottomButtonsLayout.getVisibility() == View.VISIBLE) { menuItem.hideSubItem(gallery_menu_share); } else { menuItem.showSubItem(gallery_menu_share); @@ -8976,6 +9087,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private boolean canSendMediaToParentChatActivity() { + return parentChatActivity != null && (parentChatActivity.currentUser != null || parentChatActivity.currentChat != null && ChatObject.canSendMedia(parentChatActivity.currentChat)); + } + private void setDoubleTapEnabled(boolean value) { doubleTapEnabled = value; gestureDetector.setOnDoubleTapListener(value ? this : null); @@ -9098,7 +9213,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.hideSubItem(gallery_menu_delete); } allowShare = true; - shareButton.setVisibility(View.VISIBLE); + bottomButtonsLayout.setVisibility(View.VISIBLE); + paintButton.setVisibility(View.GONE); actionBar.setTitle(LocaleController.getString("AttachGif", R.string.AttachGif)); } else { if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { @@ -9163,13 +9279,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (newMessageObject.messageOwner.ttl != 0 && newMessageObject.messageOwner.ttl < 60 * 60) { allowShare = false; menuItem.hideSubItem(gallery_menu_save); - shareButton.setVisibility(View.GONE); + bottomButtonsLayout.setVisibility(View.GONE); menuItem.hideSubItem(gallery_menu_share); } else { allowShare = true; menuItem.showSubItem(gallery_menu_save); - shareButton.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); - if (shareButton.getVisibility() == View.VISIBLE) { + paintButton.setVisibility(!isVideo && canSendMediaToParentChatActivity() ? View.VISIBLE : View.GONE); + bottomButtonsLayout.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); + if (bottomButtonsLayout.getVisibility() == View.VISIBLE) { menuItem.hideSubItem(gallery_menu_share); } else { menuItem.showSubItem(gallery_menu_share); @@ -9221,8 +9338,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } menuItem.showSubItem(gallery_menu_save); allowShare = true; - shareButton.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); - if (shareButton.getVisibility() == View.VISIBLE) { + bottomButtonsLayout.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); + if (bottomButtonsLayout.getVisibility() == View.VISIBLE) { menuItem.hideSubItem(gallery_menu_share); } else { menuItem.showSubItem(gallery_menu_share); @@ -9612,6 +9729,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat docNameTextView.setText(file.getName()); docInfoTextView.setText(builder); } + sameImage = savedState != null; } else if (object instanceof MediaController.SearchImage) { MediaController.SearchImage searchImage = (MediaController.SearchImage) object; currentPathObject = searchImage.getPathToAttach(); @@ -9685,6 +9803,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animateToY = 0; animateToScale = 1; animationStartTime = 0; + zoomAnimation = false; imageMoveAnimation = null; changeModeAnimation = null; if (aspectRatioFrameLayout != null) { @@ -10624,6 +10743,118 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return openPhoto(null, null, null, null, null, null, photos, index, provider, chatActivity, 0, 0, true, null); } + private void openCurrentPhotoInPaintModeForSelect() { + if (!canSendMediaToParentChatActivity()) { + return; + } + + File file = null; + boolean isVideo = false; + + if (currentMessageObject != null) { + isVideo = currentMessageObject.isVideo(); + if (!TextUtils.isEmpty(currentMessageObject.messageOwner.attachPath)) { + file = new File(currentMessageObject.messageOwner.attachPath); + if (!file.exists()) { + file = null; + } + } + if (file == null) { + file = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + } + } + + if (file != null && file.exists()) { + savedState = new SavedState(currentIndex, new ArrayList<>(imagesArr), placeProvider); + + final ActionBarToggleParams toggleParams = new ActionBarToggleParams().enableStatusBarAnimation(false); + toggleActionBar(false, true, toggleParams); + + File finalFile = file; + boolean finalIsVideo = isVideo; + AndroidUtilities.runOnUIThread(() -> { + int orientation = 0; + try { + ExifInterface ei = new ExifInterface(finalFile.getAbsolutePath()); + int exif = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + switch (exif) { + case ExifInterface.ORIENTATION_ROTATE_90: + orientation = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + orientation = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + orientation = 270; + break; + } + } catch (Exception e) { + FileLog.e(e); + } + final MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, finalFile.getAbsolutePath(), orientation, finalIsVideo, 0, 0, 0); + + sendPhotoType = 2; + doneButtonPressed = false; + placeProvider = new EmptyPhotoViewerProvider() { + + private final ImageReceiver.BitmapHolder thumbHolder = centerImage.getBitmapSafe(); + + @Override + public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + return thumbHolder; + } + + @Override + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { + if (parentChatActivity != null) { + parentChatActivity.sendMedia(photoEntry, videoEditedInfo, notify, scheduleDate); + } + } + + @Override + public boolean canCaptureMorePhotos() { + return false; + } + }; + selectedPhotosAdapter.notifyDataSetChanged(); + + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + + togglePhotosListView(false, false); + toggleActionBar(true, false); + + if (Build.VERSION.SDK_INT >= 21) { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + windowLayoutParams.flags = 0; + } + windowLayoutParams.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.updateViewLayout(windowView, windowLayoutParams); + windowView.setFocusable(true); + containerView.setFocusable(true); + backgroundDrawable.setAlpha(255); + containerView.setAlpha(1.0f); + + onPhotoShow(null, null, null, null, null, null, Collections.singletonList(photoEntry), 0, null); + + pickerView.setTranslationY(AndroidUtilities.dp(isCurrentVideo ? 154 : 96)); + pickerViewSendButton.setTranslationY(AndroidUtilities.dp(isCurrentVideo ? 154 : 96)); + actionBar.setTranslationY(-actionBar.getHeight()); + captionTextViewSwitcher.setTranslationY(AndroidUtilities.dp(isCurrentVideo ? 154 : 96)); + + createPaintView(); + switchToPaintMode(); + }, toggleParams.animationDuration); + } else { + showDownloadAlert(); + } + } + private boolean checkAnimation() { if (animationInProgress != 0) { if (Math.abs(transitionAnimationStartTime - System.currentTimeMillis()) >= 500) { @@ -10928,6 +11159,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.setAlpha(0); animationEndRunnable = () -> { + animationEndRunnable = null; if (containerView == null || windowView == null) { return; } @@ -11073,7 +11305,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public void closePhoto(boolean animated, boolean fromEditMode) { if (!fromEditMode && currentEditMode != 0) { if (currentEditMode == 3 && photoPaintView != null) { - photoPaintView.maybeShowDismissalAlert(this, parentActivity, () -> switchToEditMode(0)); + closePaintMode(); return; } if (currentEditMode == 1) { @@ -11111,6 +11343,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.shutdown(); containerView.removeView(photoPaintView); photoPaintView = null; + savedState = null; } currentEditMode = 0; } @@ -11326,6 +11559,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } animationEndRunnable = () -> { + animationEndRunnable = null; if (Build.VERSION.SDK_INT >= 18) { containerView.setLayerType(View.LAYER_TYPE_NONE, null); } @@ -11360,6 +11594,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ); animationInProgress = 2; animationEndRunnable = () -> { + animationEndRunnable = null; if (containerView == null) { return; } @@ -11376,8 +11611,19 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onAnimationEnd(Animator animation) { if (animationEndRunnable != null) { - animationEndRunnable.run(); - animationEndRunnable = null; + ChatActivity chatActivity = parentChatActivity; + if (chatActivity == null && parentAlert != null) { + BaseFragment baseFragment = parentAlert.getBaseFragment(); + if (baseFragment instanceof ChatActivity) { + chatActivity = (ChatActivity) baseFragment; + } + } + if (chatActivity != null) { + chatActivity.doOnIdle(animationEndRunnable); + } else { + animationEndRunnable.run(); + animationEndRunnable = null; + } } } }); @@ -12275,7 +12521,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (centerImage.hasBitmapImage() || drawTextureView && textureUploaded) { canvas.save(); canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); - canvas.translate(translateX, currentTranslationY + currentPanTranslationY); + canvas.translate(translateX, currentTranslationY + (currentEditMode != 3 ? currentPanTranslationY : currentPanTranslationY / 2)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); if (currentEditMode == 3 && keyboardSize > AndroidUtilities.dp(20)) { int trueH = getContainerViewHeight(true, 0); @@ -12432,7 +12678,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } if (currentEditMode == 3) { - photoPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY, bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); + float add = containerView.adjustPanLayoutHelper.animationInProgress() ? keyboardSize / 2f + currentPanTranslationY / 2 : 0; + photoPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY + add, bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); } if (drawCenterImage) { @@ -12515,9 +12762,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } boolean drawProgress; if (isCurrentVideo) { - drawProgress = (videoTimelineView == null || !videoTimelineView.isDragging()) && (sendPhotoType != SELECT_TYPE_AVATAR || manuallyPaused) && (videoPlayer == null || !videoPlayer.isPlaying()); - if (drawProgress && containerView.getKeyboardHeight() > 0) { - drawProgress = captionEditText.getTop() > photoProgressViews[0].getY() + photoProgressViews[0].size; + if (containerView.getKeyboardHeight() > 0) { + drawProgress = false; + } else { + drawProgress = (videoTimelineView == null || !videoTimelineView.isDragging()) && (sendPhotoType != SELECT_TYPE_AVATAR || manuallyPaused) && (videoPlayer == null || !videoPlayer.isPlaying()); } } else { drawProgress = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 8c2278f1f..7c80c1592 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -172,11 +172,11 @@ public class PopupNotificationActivity extends Activity implements NotificationC NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); classGuid = ConnectionsManager.generateClassGuid(); - statusDrawables[0] = new TypingDotsDrawable(); - statusDrawables[1] = new RecordStatusDrawable(); - statusDrawables[2] = new SendingFileDrawable(); - statusDrawables[3] = new PlayingGameDrawable(); - statusDrawables[4] = new RoundStatusDrawable(); + statusDrawables[0] = new TypingDotsDrawable(false); + statusDrawables[1] = new RecordStatusDrawable(false); + statusDrawables[2] = new SendingFileDrawable(false); + statusDrawables[3] = new PlayingGameDrawable(false); + statusDrawables[4] = new RoundStatusDrawable(false); SizeNotifierFrameLayout contentView = new SizeNotifierFrameLayout(this) { @Override @@ -1339,7 +1339,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (currentUser != null && currentUser.id == 777000) { onlineTextView.setText(LocaleController.getString("ServiceNotifications", R.string.ServiceNotifications)); } else { - CharSequence printString = MessagesController.getInstance(currentMessageObject.currentAccount).getPrintingString(currentMessageObject.getDialogId(), 0); + CharSequence printString = MessagesController.getInstance(currentMessageObject.currentAccount).getPrintingString(currentMessageObject.getDialogId(), 0, false); if (printString == null || printString.length() == 0) { lastPrintString = null; setTypingAnimation(false); @@ -1493,7 +1493,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC checkAndUpdateAvatar(); } if ((updateMask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) { - CharSequence printString = MessagesController.getInstance(currentMessageObject.currentAccount).getPrintingString(currentMessageObject.getDialogId(), 0); + CharSequence printString = MessagesController.getInstance(currentMessageObject.currentAccount).getPrintingString(currentMessageObject.getDialogId(), 0, false); if (lastPrintString != null && printString == null || lastPrintString == null && printString != null || lastPrintString != null && printString != null && !lastPrintString.equals(printString)) { updateSubtitle(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 53c425a66..29fd10777 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -134,6 +134,7 @@ import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatGreetingsView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CrossfadeDrawable; @@ -1318,7 +1319,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (ChatObject.isChannel(currentChat)) { getMessagesController().loadFullChat(chat_id, classGuid, true); } else if (chatInfo == null) { - chatInfo = getMessagesStorage().loadChatInfo(chat_id, null, false, false); + chatInfo = getMessagesStorage().loadChatInfo(chat_id, false, null, false, false); } } else { return false; @@ -1656,9 +1657,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (location == null) { return; } - File f = FileLoader.getPathToAttach(location.location, location.imageType == FileLoader.IMAGE_TYPE_ANIMATION ? "mp4" : null, true); - if (f != null && f.exists()) { - MediaController.saveFile(f.toString(), getParentActivity(), 0, null, null); + final boolean isVideo = location.imageType == FileLoader.IMAGE_TYPE_ANIMATION; + File f = FileLoader.getPathToAttach(location.location, isVideo ? "mp4" : null, true); + if (f.exists()) { + MediaController.saveFile(f.toString(), getParentActivity(), 0, null, null, () -> { + if (getParentActivity() == null) { + return; + } + BulletinFactory.createSaveToGalleryBulletin(ProfileActivity.this, isVideo).show(); + }); } } else if (id == edit_name) { presentFragment(new ChangeNameActivity()); @@ -2442,7 +2449,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getMessagesStorage().clearSentMedia(); SharedConfig.setNoSoundHintShowed(false); SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); - editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("themehint").remove("filterhint").commit(); + editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("themehint").remove("filterhint").commit(); SharedConfig.textSelectionHintShows = 0; SharedConfig.lockRecordAudioVideoHint = 0; SharedConfig.stickersReorderingHintUsed = false; @@ -3120,18 +3127,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. builder2.setMessage(LocaleController.formatString("AdminWillBeRemoved", R.string.AdminWillBeRemoved, ContactsController.formatName(user.first_name, user.last_name))); builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { if (channelParticipant != null) { - openRightsEdit(action, user.id, participant, channelParticipant.admin_rights, channelParticipant.banned_rights, channelParticipant.rank); + openRightsEdit(action, user, participant, channelParticipant.admin_rights, channelParticipant.banned_rights, channelParticipant.rank, editingAdmin); } else { - openRightsEdit(action, user.id, participant, null, null, ""); + openRightsEdit(action, user, participant, null, null, "", editingAdmin); } }); builder2.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder2.create()); } else { if (channelParticipant != null) { - openRightsEdit(action, user.id, participant, channelParticipant.admin_rights, channelParticipant.banned_rights, channelParticipant.rank); + openRightsEdit(action, user, participant, channelParticipant.admin_rights, channelParticipant.banned_rights, channelParticipant.rank, editingAdmin); } else { - openRightsEdit(action, user.id, participant, null, null, ""); + openRightsEdit(action, user, participant, null, null, "", editingAdmin); } } } @@ -3152,8 +3159,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return true; } - private void openRightsEdit(int action, int user_id, TLRPC.ChatParticipant participant, TLRPC.TL_chatAdminRights adminRights, TLRPC.TL_chatBannedRights bannedRights, String rank) { - ChatRightsEditActivity fragment = new ChatRightsEditActivity(user_id, chat_id, adminRights, currentChat.default_banned_rights, bannedRights, rank, action, true, false); + private void openRightsEdit(int action, TLRPC.User user, TLRPC.ChatParticipant participant, TLRPC.TL_chatAdminRights adminRights, TLRPC.TL_chatBannedRights bannedRights, String rank, boolean editingAdmin) { + boolean[] needShowBulletin = new boolean[1]; + ChatRightsEditActivity fragment = new ChatRightsEditActivity(user.id, chat_id, adminRights, currentChat.default_banned_rights, bannedRights, rank, action, true, false) { + @Override + protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (!isOpen && backward && needShowBulletin[0] && BulletinFactory.canShowBulletin(ProfileActivity.this)) { + BulletinFactory.createPromoteToAdminBulletin(ProfileActivity.this, user.first_name).show(); + } + } + }; fragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -3187,6 +3202,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. chatInfo.participants.participants.set(index, newParticipant); } } + if (rights == 1 && !editingAdmin) { + needShowBulletin[0] = true; + } } else if (action == 1) { if (rights == 0) { if (currentChat.megagroup && chatInfo != null && chatInfo.participants != null) { @@ -3194,9 +3212,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChannelParticipant p = ((TLRPC.TL_chatChannelParticipant) chatInfo.participants.participants.get(a)).channelParticipant; if (p.user_id == participant.user_id) { - if (chatInfo != null) { - chatInfo.participants_count--; - } + chatInfo.participants_count--; chatInfo.participants.participants.remove(a); changed = true; break; @@ -4127,7 +4143,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (chatFull.id == chat_id) { boolean byChannelUsers = (Boolean) args[2]; if (chatInfo instanceof TLRPC.TL_channelFull) { - if (chatFull.participants == null && chatInfo != null) { + if (chatFull.participants == null) { chatFull.participants = chatInfo.participants; } } @@ -4826,7 +4842,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. boolean hasPhone = user != null && !TextUtils.isEmpty(user.phone); infoHeaderRow = rowCount++; - if (!isBot && (hasPhone || !hasPhone && !hasInfo)) { + if (!isBot && (hasPhone || !hasInfo)) { phoneRow = rowCount++; } if (userInfo != null && !TextUtils.isEmpty(userInfo.about)) { @@ -4902,7 +4918,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (ChatObject.isChannel(currentChat)) { if (chatInfo != null && currentChat.megagroup && chatInfo.participants != null && !chatInfo.participants.participants.isEmpty()) { - if (!ChatObject.isNotInChat(currentChat) && currentChat.megagroup && ChatObject.canAddUsers(currentChat) && (chatInfo == null || chatInfo.participants_count < getMessagesController().maxMegagroupCount)) { + if (!ChatObject.isNotInChat(currentChat) && ChatObject.canAddUsers(currentChat) && chatInfo.participants_count < getMessagesController().maxMegagroupCount) { addMemberRow = rowCount++; } int count = chatInfo.participants.participants.size(); @@ -5417,6 +5433,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } } + if (sharedMediaLayout != null) { + sharedMediaLayout.getSearchItem().requestLayout(); + } } @Override @@ -5435,7 +5454,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (lower_part != 0) { if (lower_part > 0) { args.putInt("user_id", lower_part); - } else if (lower_part < 0) { + } else { args.putInt("chat_id", -lower_part); } } else { @@ -5493,7 +5512,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private Animator searchExpandTransition(boolean enter) { if (enter) { - getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); } if (searchViewTransition != null) { searchViewTransition.removeAllListeners(); @@ -5538,10 +5558,17 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. searchListView.setTranslationY(offset * searchTransitionProgress); emptyView.setTranslationY(offset * searchTransitionProgress); listView.setTranslationY(-offset * (1f - searchTransitionProgress)); + + listView.setScaleX(1f - 0.01f * (1f - searchTransitionProgress)); + listView.setScaleY(1f - 0.01f * (1f - searchTransitionProgress)); + listView.setAlpha(searchTransitionProgress); needLayout(true); listView.setAlpha(progressHalf); - searchListView.setAlpha(1f - progressHalf); + + searchListView.setAlpha(1f - searchTransitionProgress); + searchListView.setScaleX(1f + 0.05f * searchTransitionProgress); + searchListView.setScaleY(1f + 0.05f * searchTransitionProgress); emptyView.setAlpha(1f - progressHalf); avatarContainer.setAlpha(progressHalf); @@ -5580,8 +5607,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); - valueAnimator.setDuration(180); - valueAnimator.setInterpolator(AndroidUtilities.decelerateInterpolator); + valueAnimator.setDuration(220); + valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); searchViewTransition = valueAnimator; return valueAnimator; } @@ -5673,29 +5700,25 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (big != null) { user.photo.photo_big = big.location; - } else if (small != null) { - user.photo.photo_small = small.location; } - if (photo != null || video != null) { - if (small != null && avatar != null) { - File destFile = FileLoader.getPathToAttach(small, true); - File src = FileLoader.getPathToAttach(avatar, true); - src.renameTo(destFile); - String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; - String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUser(user, false), true); - } - if (big != null && avatarBig != null) { - File destFile = FileLoader.getPathToAttach(big, true); - File src = FileLoader.getPathToAttach(avatarBig, true); - src.renameTo(destFile); - } - if (videoSize != null && videoPath != null) { - File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); - File src = new File(videoPath); - src.renameTo(destFile); - } + if (small != null && avatar != null) { + File destFile = FileLoader.getPathToAttach(small, true); + File src = FileLoader.getPathToAttach(avatar, true); + src.renameTo(destFile); + String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; + String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUser(user, false), true); + } + if (big != null && avatarBig != null) { + File destFile = FileLoader.getPathToAttach(big, true); + File src = FileLoader.getPathToAttach(avatarBig, true); + src.renameTo(destFile); + } + if (videoSize != null && videoPath != null) { + File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); + File src = new File(videoPath); + src.renameTo(destFile); } getMessagesStorage().clearUserPhotos(user.id); @@ -6171,7 +6194,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. while (text.contains("\n\n\n")) { text = text.replace("\n\n\n", "\n\n"); } - aboutLinkCell.setText(text, true); + aboutLinkCell.setText(text, ChatObject.isChannel(currentChat) && !currentChat.megagroup); } break; case 4: @@ -6313,10 +6336,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (value == 1) { enabled = true; - } else if (value == 2) { - enabled = false; - } else { - enabled = false; } if (enabled && custom) { val = LocaleController.getString("NotificationsCustom", R.string.NotificationsCustom); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 44a6fa308..f5e722b39 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -208,7 +208,15 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter listAdapter.notifyDataSetChanged(); undoView.showWithAction(0, UndoView.ACTION_QR_SESSION_ACCEPTED, response); } else { - AndroidUtilities.runOnUIThread(() -> AlertsCreator.showSimpleAlert(SessionsActivity.this, LocaleController.getString("AuthAnotherClient", R.string.AuthAnotherClient), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text)); + AndroidUtilities.runOnUIThread(() -> { + final String text; + if (error.text.equals("AUTH_TOKEN_EXCEPTION")) { + text = LocaleController.getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn); + } else { + text = LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text; + } + AlertsCreator.showSimpleAlert(SessionsActivity.this, LocaleController.getString("AuthAnotherClient", R.string.AuthAnotherClient), text); + }); } })); }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index 1fb479cf0..171537ed1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -71,6 +71,7 @@ import org.telegram.ui.Charts.data.StackLinearChartData; import org.telegram.ui.Charts.view_data.ChartHeaderView; import org.telegram.ui.Charts.view_data.LineViewData; import org.telegram.ui.Charts.view_data.TransitionParams; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.FlatCheckBox; @@ -139,7 +140,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente public StatisticActivity(Bundle args) { super(args); int chatId = args.getInt("chat_id"); - isMegagroup = args.getBoolean("is_megagroup"); + isMegagroup = args.getBoolean("is_megagroup", false); this.chat = getMessagesController().getChatFull(chatId); } @@ -190,6 +191,10 @@ public class StatisticActivity extends BaseFragment implements NotificationCente chartsViewData[7] = createViewData(stats.languages_graph, LocaleController.getString("LanguagesChartTitle", R.string.LanguagesChartTitle), 4, true); chartsViewData[8] = createViewData(stats.mute_graph, LocaleController.getString("NotificationsChartTitle", R.string.NotificationsChartTitle), 0); + if (chartsViewData[2] != null) { + chartsViewData[2].useHourFormat = true; + } + overviewChannelData = new OverviewChannelData(stats); maxDateOverview = stats.period.max_date * 1000L; minDateOverview = stats.period.min_date * 1000L; @@ -239,6 +244,13 @@ public class StatisticActivity extends BaseFragment implements NotificationCente chartsViewData[6] = createViewData(stats.top_hours_graph, LocaleController.getString("TopHoursChartTitle", R.string.TopHoursChartTitle), 0); chartsViewData[7] = createViewData(stats.weekdays_graph, LocaleController.getString("TopDaysOfWeekChartTitle", R.string.TopDaysOfWeekChartTitle), 4); + if (chartsViewData[6] != null) { + chartsViewData[6].useHourFormat = true; + } + if (chartsViewData[7] != null) { + chartsViewData[7].useWeekFormat = true; + } + overviewChatData = new OverviewChatData(stats); maxDateOverview = stats.period.max_date * 1000L; minDateOverview = stats.period.min_date * 1000L; @@ -447,13 +459,8 @@ public class StatisticActivity extends BaseFragment implements NotificationCente recyclerListView.setOnItemClickListener((view, position) -> { if (position >= adapter.recentPostsStartRow && position <= adapter.recentPostsEndRow) { MessageObject messageObject = recentPostsLoaded.get(position - adapter.recentPostsStartRow).message; - - Bundle bundle = new Bundle(); - bundle.putInt("chat_id", chat.id); - bundle.putInt("message_id", messageObject.getId()); - bundle.putBoolean("need_remove_previous_same_chat_activity", false); - ChatActivity chatActivity = new ChatActivity(bundle); - presentFragment(chatActivity, false); + MessageStatisticActivity activity = new MessageStatisticActivity(messageObject); + presentFragment(activity); } else if (position >= adapter.topAdminsStartRow && position <= adapter.topAdminsEndRow) { int i = position - adapter.topAdminsStartRow; topAdmins.get(i).onClick(this); @@ -478,7 +485,40 @@ public class StatisticActivity extends BaseFragment implements NotificationCente }); recyclerListView.setOnItemLongClickListener((view, position) -> { - if (position >= adapter.topAdminsStartRow && position <= adapter.topAdminsEndRow) { + if (position >= adapter.recentPostsStartRow && position <= adapter.recentPostsEndRow) { + MessageObject messageObject = recentPostsLoaded.get(position - adapter.recentPostsStartRow).message; + + final ArrayList items = new ArrayList<>(); + final ArrayList actions = new ArrayList<>(); + final ArrayList icons = new ArrayList<>(); + + items.add(LocaleController.getString("ViewMessageStatistic", R.string.ViewMessageStatistic)); + actions.add(0); + icons.add(R.drawable.msg_stats); + + items.add(LocaleController.getString("ViewMessage", R.string.ViewMessage)); + actions.add(1); + icons.add(R.drawable.menu_chats); + + + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setItems(items.toArray(new CharSequence[actions.size()]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> { + if (i == 0) { + MessageStatisticActivity activity = new MessageStatisticActivity(messageObject); + presentFragment(activity); + } else if (i == 1) { + Bundle bundle = new Bundle(); + bundle.putInt("chat_id", chat.id); + bundle.putInt("message_id", messageObject.getId()); + bundle.putBoolean("need_remove_previous_same_chat_activity", false); + ChatActivity chatActivity = new ChatActivity(bundle); + presentFragment(chatActivity, false); + } + }); + + showDialog(builder.create()); + + } else if (position >= adapter.topAdminsStartRow && position <= adapter.topAdminsEndRow) { int i = position - adapter.topAdminsStartRow; topAdmins.get(i).onLongClick(chat, this, progressDialog); return true; @@ -537,11 +577,12 @@ public class StatisticActivity extends BaseFragment implements NotificationCente return fragmentView; } - private ChartViewData createViewData(TLRPC.StatsGraph graph, String title, int graphType, boolean isLanguages) { + public static ChartViewData createViewData(TLRPC.StatsGraph graph, String title, int graphType, boolean isLanguages) { if (graph == null || graph instanceof TLRPC.TL_statsGraphError) { return null; } ChartViewData viewData = new ChartViewData(title, graphType); + viewData.isLanguages = isLanguages; if (graph instanceof TLRPC.TL_statsGraph) { String json = ((TLRPC.TL_statsGraph) graph).json.data; try { @@ -566,11 +607,11 @@ public class StatisticActivity extends BaseFragment implements NotificationCente return viewData; } - private ChartViewData createViewData(TLRPC.StatsGraph graph, String title, int graphType) { + private static ChartViewData createViewData(TLRPC.StatsGraph graph, String title, int graphType) { return createViewData(graph, title, graphType, false); } - private static ChartData createChartData(JSONObject jsonObject, int graphType, boolean isLanguages) throws JSONException { + public static ChartData createChartData(JSONObject jsonObject, int graphType, boolean isLanguages) throws JSONException { if (graphType == 0) { return new ChartData(jsonObject); } else if (graphType == 1) { @@ -703,7 +744,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v; if (viewType >= 0 && viewType <= 4) { - v = new ChartCell(parent.getContext(), viewType) { + v = new ChartCell(parent.getContext(), viewType, sharedUi) { @Override protected void onDraw(Canvas canvas) { if (getTranslationY() != 0) { @@ -1058,7 +1099,97 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } } - public class ChartCell extends FrameLayout { + private class ChartCell extends BaseChartCell { + + public ChartCell(@NonNull Context context, int type, BaseChartView.SharedUiComponents sharedUi) { + super(context, type, sharedUi); + } + + @Override + public void zoomCanceled() { + cancelZoom(); + } + + @Override + public void onZoomed() { + if (data.activeZoom > 0) { + return; + } + performClick(); + if (!chartView.legendSignatureView.canGoZoom) { + return; + } + final long x = chartView.getSelectedDate(); + if (chartType == 4) { + data.childChartData = new StackLinearChartData(data.chartData, x); + zoomChart(false); + return; + } + + if (data.zoomToken == null) { + return; + } + + cancelZoom(); + final String cacheKey = data.zoomToken + "_" + x; + ChartData dataFromCache = childDataCache.get(cacheKey); + if (dataFromCache != null) { + data.childChartData = dataFromCache; + zoomChart(false); + return; + } + + TLRPC.TL_stats_loadAsyncGraph request = new TLRPC.TL_stats_loadAsyncGraph(); + request.token = data.zoomToken; + if (x != 0) { + request.x = x; + request.flags |= 1; + } + ZoomCancelable finalCancelabel; + lastCancelable = finalCancelabel = new ZoomCancelable(); + finalCancelabel.adapterPosition = recyclerListView.getChildAdapterPosition(ChartCell.this); + + chartView.legendSignatureView.showProgress(true, false); + + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + ChartData childData = null; + if (response instanceof TLRPC.TL_statsGraph) { + String json = ((TLRPC.TL_statsGraph) response).json.data; + try { + childData = createChartData(new JSONObject(json), data.graphType, data == languagesData); + } catch (JSONException e) { + e.printStackTrace(); + } + } else if (response instanceof TLRPC.TL_statsGraphError) { + Toast.makeText(getContext(), ((TLRPC.TL_statsGraphError) response).error, Toast.LENGTH_LONG).show(); + } + + ChartData finalChildData = childData; + AndroidUtilities.runOnUIThread(() -> { + if (finalChildData != null) { + childDataCache.put(cacheKey, finalChildData); + } + if (finalChildData != null && !finalCancelabel.canceled && finalCancelabel.adapterPosition >= 0) { + View view = layoutManager.findViewByPosition(finalCancelabel.adapterPosition); + if (view instanceof ChartCell) { + data.childChartData = finalChildData; + ((ChartCell) view).chartView.legendSignatureView.showProgress(false, false); + ((ChartCell) view).zoomChart(false); + } + } + cancelZoom(); + }); + }, null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); + ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); + } + + @Override + public void loadData(ChartViewData viewData) { + viewData.load(currentAccount, classGuid, chat.stats_dc, recyclerListView, adapter, diffUtilsCallback); + } + } + + public static abstract class BaseChartCell extends FrameLayout { BaseChartView chartView; BaseChartView zoomedChartView; ChartHeaderView chartHeaderView; @@ -1073,7 +1204,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente int chartType; @SuppressLint("ClickableViewAccessibility") - public ChartCell(@NonNull Context context, int type) { + public BaseChartCell(@NonNull Context context, int type, BaseChartView.SharedUiComponents sharedUi) { super(context); setWillNotDraw(false); chartType = type; @@ -1167,83 +1298,14 @@ public class StatisticActivity extends BaseFragment implements NotificationCente chartView.setDateSelectionListener(date -> { - cancelZoom(); + zoomCanceled(); chartView.legendSignatureView.showProgress(false, false); }); chartView.legendSignatureView.showProgress(false, false); chartView.legendSignatureView.setOnTouchListener(new RecyclerListView.FoucsableOnTouchListener()); chartView.legendSignatureView.setOnClickListener(v -> { - if (data.activeZoom > 0) { - return; - } - performClick(); - if (!chartView.legendSignatureView.canGoZoom) { - return; - } - final long x = chartView.getSelectedDate(); - if (chartType == 4) { - data.childChartData = new StackLinearChartData(data.chartData, x); - zoomChart(false); - return; - } - - if (data.zoomToken == null) { - return; - } - - cancelZoom(); - final String cacheKey = data.zoomToken + "_" + x; - ChartData dataFromCache = childDataCache.get(cacheKey); - if (dataFromCache != null) { - data.childChartData = dataFromCache; - zoomChart(false); - return; - } - - TLRPC.TL_stats_loadAsyncGraph request = new TLRPC.TL_stats_loadAsyncGraph(); - request.token = data.zoomToken; - if (x != 0) { - request.x = x; - request.flags |= 1; - } - ZoomCancelable finalCancelabel; - lastCancelable = finalCancelabel = new ZoomCancelable(); - finalCancelabel.adapterPosition = recyclerListView.getChildAdapterPosition(ChartCell.this); - - chartView.legendSignatureView.showProgress(true, false); - - int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { - ChartData childData = null; - if (response instanceof TLRPC.TL_statsGraph) { - String json = ((TLRPC.TL_statsGraph) response).json.data; - try { - childData = createChartData(new JSONObject(json), data.graphType, data == languagesData); - } catch (JSONException e) { - e.printStackTrace(); - } - } else if (response instanceof TLRPC.TL_statsGraphError) { - Toast.makeText(context, ((TLRPC.TL_statsGraphError) response).error, Toast.LENGTH_LONG).show(); - } - - ChartData finalChildData = childData; - AndroidUtilities.runOnUIThread(() -> { - if (finalChildData != null) { - childDataCache.put(cacheKey, finalChildData); - } - if (finalChildData != null && !finalCancelabel.canceled && finalCancelabel.adapterPosition >= 0) { - View view = layoutManager.findViewByPosition(finalCancelabel.adapterPosition); - if (view instanceof ChartCell) { - data.childChartData = finalChildData; - ((ChartCell) view).chartView.legendSignatureView.showProgress(false, false); - ((ChartCell) view).zoomChart(false); - } - } - cancelZoom(); - }); - }, null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); - ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); - + onZoomed(); }); zoomedChartView.legendSignatureView.setOnClickListener(v -> { zoomedChartView.animateLegend(false); @@ -1266,7 +1328,13 @@ public class StatisticActivity extends BaseFragment implements NotificationCente addView(linearLayout); } - private void zoomChart(boolean skipTransition) { + public abstract void onZoomed(); + + public abstract void zoomCanceled(); + + abstract void loadData(ChartViewData viewData); + + public void zoomChart(boolean skipTransition) { long d = chartView.getSelectedDate(); ChartData childData = data.childChartData; // if (childData == null) return; @@ -1503,13 +1571,13 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } errorTextView.setVisibility(View.GONE); - chartView.legendSignatureView.isTopHourChart = viewData == topHoursData; - chartHeaderView.showDate(viewData != topHoursData); + chartView.legendSignatureView.isTopHourChart = viewData.useHourFormat; + chartHeaderView.showDate(!viewData.useHourFormat); if (viewData.chartData == null && viewData.token != null) { progressView.setAlpha(1f); progressView.setVisibility(View.VISIBLE); - viewData.load(currentAccount, classGuid, chat.stats_dc, recyclerListView, adapter, diffUtilsCallback); + loadData(viewData); chartView.setData(null); return; } else if (!enterTransition) { @@ -1517,8 +1585,8 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } chartView.setData(viewData.chartData); - chartHeaderView.setUseWeekInterval(viewData == topDayOfWeeksData); - chartView.legendSignatureView.setUseWeek(viewData == topDayOfWeeksData); + chartHeaderView.setUseWeekInterval(viewData.useWeekFormat); + chartView.legendSignatureView.setUseWeek(viewData.useWeekFormat); chartView.legendSignatureView.zoomEnabled = !(data.zoomToken == null && chartType != 4); zoomedChartView.legendSignatureView.zoomEnabled = false; @@ -1629,7 +1697,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente break; } } - cancelZoom(); + zoomCanceled(); if (allDisabled) { checkBox.denied(); return; @@ -1650,7 +1718,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente if (!checkBox.enabled) { return false; } - cancelZoom(); + zoomCanceled(); int n = checkBoxes.size(); for (int i = 0; i < n; i++) { checkBoxes.get(i).checkBox.setChecked(false); @@ -1693,12 +1761,12 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } - private static class ZoomCancelable { + public static class ZoomCancelable { int adapterPosition; boolean canceled; } - private class ChartViewData { + public static class ChartViewData { public boolean isError; public String errorMessage; @@ -1714,6 +1782,9 @@ public class StatisticActivity extends BaseFragment implements NotificationCente boolean loading; boolean isEmpty; + boolean isLanguages; + boolean useHourFormat; + boolean useWeekFormat; public ChartViewData(String title, int grahType) { this.title = title; @@ -1732,7 +1803,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente if (response instanceof TLRPC.TL_statsGraph) { String json = ((TLRPC.TL_statsGraph) response).json.data; try { - chartData = createChartData(new JSONObject(json), graphType, this == languagesData); + chartData = createChartData(new JSONObject(json), graphType, isLanguages); zoomToken = ((TLRPC.TL_statsGraph) response).zoom_token; if (graphType == 4 && chartData.x != null && chartData.x.length > 0) { long x = chartData.x[chartData.x.length - 1]; @@ -1846,19 +1917,15 @@ public class StatisticActivity extends BaseFragment implements NotificationCente private void recolorRecyclerItem(View child) { if (child instanceof ChartCell) { ((ChartCell) child).recolor(); - } - - if (child instanceof ShadowSectionCell) { + } else if (child instanceof ShadowSectionCell) { Drawable shadowDrawable = Theme.getThemedDrawable(ApplicationLoader.applicationContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow); Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)); CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); combinedDrawable.setFullsize(true); child.setBackground(combinedDrawable); - } - if (child instanceof ChartHeaderView) { + } else if (child instanceof ChartHeaderView) { ((ChartHeaderView) child).recolor(); - } - if (child instanceof OverviewCell) { + } else if (child instanceof OverviewCell) { ((OverviewCell) child).updateColors(); } } @@ -2082,7 +2149,6 @@ public class StatisticActivity extends BaseFragment implements NotificationCente arrayList.add(new ThemeDescription(recyclerListView, ThemeDescription.FLAG_CHECKTAG, new Class[]{ManageChatTextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText5)); arrayList.add(new ThemeDescription(recyclerListView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{ManageChatUserCell.class, ManageChatTextCell.class, HeaderCell.class, TextView.class, PeopleNearbyActivity.HintInnerCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); - if (isMegagroup) { for (int i = 0; i < 6; i++) { ChartViewData chartViewData; @@ -2130,7 +2196,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente return arrayList; } - private void putColorFromData(ChartViewData chartViewData, ArrayList arrayList, ThemeDescription.ThemeDescriptionDelegate themeDelegate) { + public static void putColorFromData(ChartViewData chartViewData, ArrayList arrayList, ThemeDescription.ThemeDescriptionDelegate themeDelegate) { if (chartViewData != null && chartViewData.chartData != null) { for (ChartData.Line l : chartViewData.chartData.lines) { if (l.colorKey != null) { @@ -2390,7 +2456,6 @@ public class StatisticActivity extends BaseFragment implements NotificationCente secondary[i].setTextColor(Theme.getColor(colorKey)); } } - } } @@ -2575,11 +2640,18 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } boolean isAdmin = false; - if (currentUser != null && currentParticipant != null && currentUser.channelParticipant.admin_rights != null && currentUser.channelParticipant.admin_rights.add_admins) { - isAdmin = currentParticipant.channelParticipant.admin_rights == null; - items.add(isAdmin ? LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin) : LocaleController.getString("EditAdminRights", R.string.EditAdminRights)); - icons.add(isAdmin ? R.drawable.actions_addadmin : R.drawable.actions_permissions); - actions.add(0); + if (currentUser != null && currentParticipant != null && currentUser.user_id != currentParticipant.user_id) { + TLRPC.ChannelParticipant channelParticipant = currentParticipant.channelParticipant; + boolean canEditAdmin = currentUser.channelParticipant.admin_rights != null && currentUser.channelParticipant.admin_rights.add_admins; + if (canEditAdmin && (channelParticipant instanceof TLRPC.TL_channelParticipantCreator || channelParticipant instanceof TLRPC.TL_channelParticipantAdmin && !channelParticipant.can_edit)) { + canEditAdmin = false; + } + if (canEditAdmin) { + isAdmin = channelParticipant.admin_rights == null; + items.add(isAdmin ? LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin) : LocaleController.getString("EditAdminRights", R.string.EditAdminRights)); + icons.add(isAdmin ? R.drawable.actions_addadmin : R.drawable.actions_permissions); + actions.add(0); + } } AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity()); @@ -2587,7 +2659,15 @@ public class StatisticActivity extends BaseFragment implements NotificationCente boolean finalIsAdmin = isAdmin; builder.setItems(items.toArray(new CharSequence[actions.size()]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> { if (actions.get(i) == 0) { - ChatRightsEditActivity newFragment = new ChatRightsEditActivity(user.id, chat.id, finalCurrentParticipant.channelParticipant.admin_rights, null, finalCurrentParticipant.channelParticipant.banned_rights, finalCurrentParticipant.channelParticipant.rank, ChatRightsEditActivity.TYPE_ADMIN, true, finalIsAdmin); + boolean[] needShowBulletin = new boolean[1]; + ChatRightsEditActivity newFragment = new ChatRightsEditActivity(user.id, chat.id, finalCurrentParticipant.channelParticipant.admin_rights, null, finalCurrentParticipant.channelParticipant.banned_rights, finalCurrentParticipant.channelParticipant.rank, ChatRightsEditActivity.TYPE_ADMIN, true, finalIsAdmin) { + @Override + protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (!isOpen && backward && needShowBulletin[0] && BulletinFactory.canShowBulletin(fragment)) { + BulletinFactory.createPromoteToAdminBulletin(fragment, user.first_name).show(); + } + } + }; newFragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -2597,6 +2677,9 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } else { finalCurrentParticipant.channelParticipant.admin_rights = rightsAdmin; finalCurrentParticipant.channelParticipant.rank = rank; + if (finalIsAdmin) { + needShowBulletin[0] = true; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ViewPagerFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/ViewPagerFixed.java index 20280a0c4..0ef46b4fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ViewPagerFixed.java @@ -32,6 +32,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScroller; @@ -272,10 +273,6 @@ public class ViewPagerFixed extends FrameLayout { velocityTracker.addMovement(ev); } if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && checkTabsAnimationInProgress()) { - View child = findScrollingChild(this, ev.getX(), ev.getY()); - if (child != null && (child.canScrollHorizontally(1) || child.canScrollHorizontally(-1))) { - return false; - } startedTracking = true; startedTrackingPointerId = ev.getPointerId(0); startedTrackingX = (int) ev.getX(); @@ -302,6 +299,13 @@ public class ViewPagerFixed extends FrameLayout { } else if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) { additionalOffset = 0; } + + if (!startedTracking && ev != null) { + View child = findScrollingChild(this, ev.getX(), ev.getY()); + if (child != null && (child.canScrollHorizontally(1) || child.canScrollHorizontally(-1))) { + return false; + } + } if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && !startedTracking && !maybeStartTracking) { startedTrackingPointerId = ev.getPointerId(0); maybeStartTracking = true; @@ -624,6 +628,7 @@ public class ViewPagerFixed extends FrameLayout { public void setTab(Tab tab, int position) { currentTab = tab; currentPosition = position; + setContentDescription(tab.title); requestLayout(); } @@ -938,6 +943,14 @@ public class ViewPagerFixed extends FrameLayout { public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { return super.scrollHorizontallyBy(dx, recycler, state); } + + @Override + public void onInitializeAccessibilityNodeInfo(@NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state, @NonNull AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(recycler, state, info); + if (isInHiddenMode) { + info.setVisibleToUser(false); + } + } }); listView.setPadding(AndroidUtilities.dp(7), 0, AndroidUtilities.dp(7), 0); listView.setClipToPadding(false); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blockpanel_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/blockpanel_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..83faa725d6f2e3a3edbbac50905559f23d026ebf GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-c!3HFEzPi^4q*&4&eH|GXHuiJ>Nn{1`Em9*q z(|mmyw18|52FCVG1{NTT5s0OL7-+x(Cb$UG0%kay86^36!*&HACFbek7{Vc&oRW|* jfjNoIP2m}X;RB$(Sqz$MF6K-Fs$lSR^>bP0l+XkKa_}8( literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png b/TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..7091d810af37e97c8e95ad502b33a4e5dc96393d GIT binary patch literal 979 zcmeAS@N?(olHy`uVBq!ia0vp^E+EXo1|%(nCvRe4V4mga;uuoF_;yZf(QOA2SLsQ2 z42+G9XHJ>=^hRo0+Pi@I1txbAHEP{w&YbyM_$eRDopR%_WuYFa(Ur4yD(05Gv#q?v z`{wkN{S~bLR{i^T^!oaSG=)Y7g+pGmBu=mhe0z6Sno~D!j|G>IlS}vB>czLW<#ckU z9#r1*YTs8G;RBpL9L$rqZrytHLU!h_FE2L<97@}Md-x%qa7O*g|XP58XzyM&b5FOOYf$(z?M=4n0AVzbm6RUI@Jb%pU~p9-bw^Tn_h%*HO^S>8SfoTb*cL2l%66^s^z;<;Et!<}J=tSM zcEhHa#a=6&%qHbl_!=@9>MRlxQ@3f}cH;(bRceGw^Cq45Y62%ubgZ!t=@jgUlXdQ1 zzAV+%#r5uyT0*E-%kh>0M)uowJcci*nhHhOIeEHIb*9yjEa{?O^tPd&hgo)($hBodnUAxVP0 zKK}03Cv#q{sg80x=D2!myUOxq@|(B=bAciso)wt8I2Zrs@th_f!E#C=^!Vyozn1+> zx{}8s{MShD>iv+YxUI3%o*sXAFG=m>r_YNPO|mUJdOK-V{IMH>tW7I~-22n=v$A66 z&zxH9GU>^5K|#UzL#!;7f2EW?^Nlxc>N7XnmQ%vH-uwMj$LX4zUiEXEq@9nQ5VPn0 zd;hmzetN~MT7P=sD&x6byN)Ps2`zJteXOLZs8!MIUQw!*^m0P^!?(-y3ud}yv(IBl zE}ik}6pM(p<4Yl>{jjxXME_1?Sykv+iFY~`A7y+@f@Ea-CV z%wzjvbKI-$>xo7Bw56Ya_wh-ohF7D|qbB!?*7OQ@w$HV@)vR_KO1==fxuoFbo3`-e xbaSo4CF$nh|M@rl=VSbPs=obzw9c-5j4qMfdAH0qKLch~22WQ%mvv4FO#mHft>FLw literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png b/TMessagesProj/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4f9bc6ba764314a5c59cc5bae1ea1a1a1a8d50aa GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^jv&mz0wh)bF`ffb4?SHRLn;{G-ehDu6d-f_qrL-+ zh{y8|1*aE6rHw)jLa_=~&H@}PRxTayHZV#j7;h8js92j+z4znqdi@UvncpAxPv5sL zFx}h#Qxo<-B#X9yNAegD;I`N|NM&(|xME^dC< Uyysww4A8R-p00i_>zopr0Gh#T2mk;8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/map_pin_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/map_pin_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..a5cd5b17e1965079c0cbef9c911e45a079967426 GIT binary patch literal 793 zcmeAS@N?(olHy`uVBq!ia0vp^iXhCv1|-9u9Lfh$Ea{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`-|zfEmFCNt$*nvH~jU@pN$viQs%2YMUVv zC@^n(^_*u)YFUChF0Ba@6dHv+lb`-=;6s6o_|6IEl5xi?1CQU%{+agd_D%E6F1n{CF1mj^ ziK8frv*1Nr{TuPu{O#Ranb#ii^nLV2Wp~s|LlyoLcXpkdV-=Ql{FM8D8N;vop$(Z2 ze$JQ^+~xJS{14yrJzeI9U80@qIlrV9hv!{y_I_2pV)NbL&_mH5)|&`97|qcReZMOA zkz33oFOj@r{_3rgp1T(sUbwV5Xsge(U(58K+pXVpRAW;3q0jD0oC=)9?dyUK)#8_E z2CDMi`?GU)Z=Lc|^R6GdldJT9%S^m=>_~M-sJ&*9tGPw(+RY*}4V`9oUN8;cxKHEc zyuLXx_FMO#*UWHcb-$=~c*_H;FOP0o7w3POSRc|6GeO~+icsjHSHuY_Gv8TiWGa-0LdO|{Y%y2RS7pI*Ai z@6giL`=?q0)3t>%oJ$;q80G5B?7~zG*e|qsvQ+%I`6FWD0fj>{8#pDB8rtJ4`fjiF z@Mz%VQ98pY&6rnN;CtgiuBVUJ1|v4XXAW}?@X37G^kDn4Bknl`|DOvRKVee(^d}%p zu9!LZxA{NW#G2Q#$}!g>BmJ4qem+(pYklr?)ouTrxtn=&!WYCgma+cp=K90d*C}3B SrsSyuN}rytelF{r5}E)CuSggG literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/map_pin_circle.png b/TMessagesProj/src/main/res/drawable-hdpi/map_pin_circle.png new file mode 100644 index 0000000000000000000000000000000000000000..0216074abb43feefe7b689b567c33412cba466c1 GIT binary patch literal 529 zcmeAS@N?(olHy`uVBq!ia0vp^iXhCv1|-9u9Lfh$Ea{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`-|zfEmFCNt$*nvH~h@@pN$viQs%2deDp6 zP++c#x1&wO#|MFbnG#+9FxVgH?)dUz<@_s?kIQw5@BPgf6#IdD)p4#QQI`m_&d&=P zFRgp2Bf>SQQBmddy(e#Tj1;}5X-xpa5Axa%_FjK8{Z0AQugTAAIt4$!+?Dt1?kdhk zbIXK3yw!I9O1`~3I`icA<=>VqT3nl3zJ1HXh=Xe90J`%JdG zZryM&a$ex~Evd%N!fRhdXt}5~u`W1rc+;Z8@4og|)_&(^I&|n>-=ce0+j3LCoXHk= zdylo^!MvyA-f=07Y4`cQ@W$K@-6N~Gzruw( oJ^rP();$}>VAdcYycXFQZ~6J$gvp&xwu9ou)78&qol`;+0C^qO2LJ#7 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/map_pin_cone2.png b/TMessagesProj/src/main/res/drawable-hdpi/map_pin_cone2.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f1fe1f5d055b65868dd6c478dc77d6fa0940d9 GIT binary patch literal 2544 zcmb7GYdjN*8=lB<9g8lCVQ9s&h|bb+ZQABC*5sNT_huB?2+ay%WEpZNvB~{X?sJLc zuDO&;shCUUdN^weah(5$|Nry(thUZQ{||W ze*PA2+gk=f!9Q9jb9j2Kb+=~On@7@RR>Hj(vO_4F14ISoY=p49ApQQHv#;J_QaMB7~&Z|EB<`1<9lWgY3~>>ut!i^U-HXG|C5Do=FjBVxKW*5 z&}my};qw|(r=!DYJo%MV)GoikWG<%5onqKfY=Fxv8@`JFnio*HTI zb>Cj=SWAl88<=V)dg<}JpEL4(Wr|$Q3(@lszq&IJR^!f@FcdL)je+xV_{{e7t|&Ca zj$dpGaLvOp%oip4UNzw|9wWzyWXP!TVLoKps1QCqnXWu4ST)#w+2j3Ur!D{8V%S}i z0kT`>^N(tg9$lexs~G2ss6dt(#VGAnV=CF{1jBEbvrztQrM9o@yU)tpobKPmpS8rz z4`ko&TiDppV-mcy?-9I+l=KFm{_-et3LE6mt#G)%p7|6 z2D2{vKr2btQB9t+OGQ@lKNhESaf9N>3#F_BOzbiPoq@!=EK?hk2ZMFE6V+}bZ3uV? zOAT3W;>f+qii^+e*|3Fbx1^Riw8nlvRTAtQ_kNd@-O!W#J=LB2nM zF>Wi>Yxd8k0nNIfsc#2u&-9&FDB89CCBfAbKH}r%18rB;Rco3dOsL)+(UpuZ=!6v0 zcxhTBsSu;Wa;y%2Ak8yflY1|4Iq#24Ey*M6vF=~CB1c%}!#n<^^sz<;O44-*@pgS7 zon{h+6Dhx$NZ2~a(CH!NS=*{ep{w;6`MBSg%t3}IISmvr|8^1n57LwLP5sjp)&Yr* zdbGZXYIvD!7I|U4IKIo%cdT5$cTx5H(iqs|yLA8cQ{8Z&bD#UeZ=94%gY}g14Pl3I zcL@Uc9W5tOBtGkrDgA~}Qyw--r~ar2dH0LUsT}QSV4I$9uII<&%kaSg4s7)$#z=jh z2+48#3MRQZ_KakLsy)8;mmKbsLPjJZ$yR*E#pQt!1)?7MNDsN~XzEf*Aah)~=p$`&WT9R(GOv+TFM=my7i_#0G z8R#cSmL7v3WtFWwY74D9#MzvY5rwGHwe>;IEG}a!uhC9a?5<2bq^{&5MXNmPu%GH` zIs+nmw0<^_yC;Nb7TvK*w~d(g`m+b|AgJ_P6w~=+kp%{Ju;>9nDpbCI*gpki;c2C{skamsYQ)B1?V1YR zd5nfgxPR?v7N-8LG@=%5;Q?EnWI2a8o(+waT?C&`g5{^b+xc~#k;^B+Xf+wd;CQMv z2Y(y7T31Bk*MBleQau!0FrUxr&@n&TW@DCec@87-L}XY*v)CPW?{qc#uTjNw32pF0 ziP6PCi(izf)$rgh**ELt3(bMPDp?hwj|h=>)2n(MYxJrW97>yQMxh2Sp$$1DW3$O& zovfVr+%#G!dst0V0~1kX20w#HCipfaq1hu3l~^fX|JCC9^Jbm{Y;XwLCH&E}@dQ|QK>FO!b*n%Qjw z?GbZwGkGChDkicdO+L~cYHSH=yzBEyF)a2#fotOrD85h}zRjNh^mfxw<0$9|e7Y)5 z%2Q8uqg{*nCqvKgNU=)dLu%Zq0^Pe;bo7>t!4vwFWxRG8T)DjGn`382S8cdh0I$yO z3*op$%_P8MSt}yeA*TE$M7zH}gruc6#(Ac_S7BsFW7mG#n<|)bJ98uy5SFJbY-hV1 zgXj~uz@0I0n4kt$`7I?*yyO{rCpQ)oC|*I=v*0;mPW}-;&6v}gWsjeg+>%$<5A2vD zeetBeTdj$dH@f0!qn}4>h-)srfI743U%FHvVsIbk|E5CC!n><9@o6`SSciTv- z+%vk{Frn5^6Ga&n{euk$*mg^fUEDb53@yhNaH0^RrAUusPs l^OyKfQu)8_bX(;8JwW7|79V7lul#T9!kA)_6()a1`~&&$$npRH literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/map_pin_photo.png b/TMessagesProj/src/main/res/drawable-hdpi/map_pin_photo.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f5769249a792eabbfdb34946991f685db667af GIT binary patch literal 3539 zcmbtX`8O197oRb*WQ!!*lJV^FrqSwe9*L?-o#uNd8!r57S}p}%RI~OLGJI0&nnzV!|3jL|IEA=Dthy^xV@GeAyz)W zdw6*G#r*tyD;Ny!3kV1}>*(mHB%7rLTNxcX>x%e0SY-Y6l9}amfgF!?HDOJ`Ta;K< z_PxCqKsJB007&EZiS%+}6imV^KipRVX=6Ft`!Uz0nWWUW$f zJ8sb6(?Xx8ZS=2rJdPf3@*|dtyue}>vn|(rbC{dg2m4ln)0@@;xi#j53eKN*8$+L# zK`IF9fRlc|KyooZx+0HyNp`a}4NKqTd17ZHW@Cu1jgf!HoVJ?Pw}zGWWEzES%3}FI zU9&vddZD#5NpHZ7Bhw?*E?tVM(s}T=U?|fuO?5;0t*_Jx}%v!ZribL+1 zpvHF2fh5@a<P~l;BtzaN$K=0@vzNn~3LQ4M5m;He(EnML8 z;K$IhBL&j{Q>t!a-J#BV%O#D%&EqFzNR#z8Q|oUe0G!Am87U8;?xacIZza>gU0{eH zcFioj=*)UBgJ2SQFI=_aIxuYdq@IU0SSy@DjOV^G*4)nNqN~n$pE$m9R$!p%&CtcB z--r9OGU2PfqbaU}!G35C0;h{6Z_tEjkI{`M%!k~?jTIHa?nMylIxM`+?4Z<#T9FnA zX+KOhNs&$+8y)TCd)8heDFslfYqgXst?4o}F04-*-dZK<*;!e&4cJ&%Ngl`K8g8i2 zUw*I2N%tOgN)T>MoqRT+=>I3_iTg4?G52e+n7q7vv&avsn$-n>Izuj07~%HUeOdMj zT?(VKJrPme=UI}n$;nOM1(M#eIm{c#c$mOoTOfl=xMVdT7TaYN4^l8rGQbVF*=xt_ zZLS}evf(@VQ#31?-8l7G@H;2~+;=WWMbQ}_W_tH7ziplc-UNUQx*wb)7HOGbk1u3H zm^eF=hyl+X!?CdgLkI92S#F*3Fs6J+^qcmQu#DIN<&XK#V=Vp>9)ra2&M6AQr|8!{ z_$hZf$LzfnQSIJx;=>7R{CEQppOd@FHZvj|u0)ZA&!c5ln73Wnc9QrXKfub^oJ%lJ zA5juLuEwj@ySQX!AodaAY&=^Qj23%v%GFHshX4>;V6amy8a8Er#e49dK$)OqDHh#< zSS4Q`yfrWkx%*$+GKZaIbD38MEiMjI5IH@VDmP?i_u_#fQ#_A z;^f1TsS_>qnvIm9`V%?`B0tnbFz6_aWl2>QeA!TrF+nV>I{I{B8d$-mn1M^vR$lzH z&+33h9Y$%eOy@*T`d{$;0f@xZd)t3B)^r(zM7wT;)MKhSmy-s-aKm5h^4}$WF&&Zg zUk-Scn$@djj>Dxt&Tw!f%<7T9jCKt3;CI79l>?5O7^#TGU&{om--U;*l9%EW9G>mo zY#!%n5LR+YPu$IL>ecx}w4adr?J$$Ietmhe@gi9f=uIcMn`3SRT{HB$oV+X-Z;TRlZFUoU4 z{;ljFIXb_uAX@B@9TK+zCHmcSJX6&|p+zJLawHJ3CoON#!G;36Gh9{mv1z`kq(Y>a745W2Pmj#dr`L&hcAN}>waZT+c7`G{N^TM zpO#9*)chIeoZgb#Q?(l}dof^U+}bIIWUp=7Y|BL}*yBK1huyfkPZS#~Ffb>j&U686 zJ?-S+?Be30pf|4M`u9T-bD71v#BQ{$eJQynBGLrQo;A`j&5g6dh^zTe)QuEaLQQLu zm~z-XW`s_qh7hkQ{rd~Yr0j%u89;4yBVKE~ffZ`8SLBeG>t@6xnYR3C88|OP$e*eT z2Vqd`+NZmC;JbuK<{ReC^LL1Reb6x?5fzWzXFdmM`_DhUYjYz0F9Gx6vU{7k?_dT~ zq!H;jaqW1j;Cyh|lrt{zRaX_S6D;xpnY!vK{~4GkZJCWoL6ABRIb3Lq@cfS--L;vU z`%@kSYpe{K5Ze7}OwU{K3WaLV+D;A3BL*rYb#qAb9n4eb;h$ zP3X~TS`mb=xYR)sznK~L6O-bNh1PZ9|_>^LWwO~aeTUwHm-~# zB?+?M%r)tW7OaYAx2+F$)?zXdmZA0M>QRZ>CrNik=4-Dl1{?t?@Gn{86e;^cHgUdB zJ#~=%I?TbEmO*RW=)dRD`LZ6p&7kJSRF4#El})23Vdk81>R-EL)<;~0bqj(?l%G{H z9szK3M$4up-Zmtd?H0|`xsiEqCr?`)I@8!tXp7!cW{ET3_m)YKqV{V=OE^4=Gvf?DI7FPQ&}%6f-+Izwz)j? z6cOvCKa_}E`KY^+e~4svjCpbEB4T4VOnjC7X%_I?UgjRRJ~Q`5;^&?aOQ}$ukn=R( z%4TQJPC54>BTM(e(d#k2S4U?bkrF1e(}WRe40BCh076c`Tz}&T09h||t`Awj!R(Q` z{E^NE$S+6f8J`-t1&F34AreY6vyD+3?H>di4mMsI4t91)pbjo2 zwd3ClKQ{lqq|en>BRK@HYox_A)M3ZCY-l`_@SmN#Urm{@IrU6Lb9bC=#Sx0~mqM6H$pM1d|l-}w_B7|yZ z8fWav#k3Bee?;Y03Lp`xjQpcu3VeDcb5Rr3b>^nyGmY%$aJGR35Hg1b%j?+xkMxhE a>8Mi;!^WNax|9EIRwg$rj7kmNp8N+f8{cOD literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..409ef0fa95e5697398bc148fea722414dfb3a869 GIT binary patch literal 1079 zcmV-71jze|P)G3>;(UU6oQSfPQgA+ z6w$&$FilXwUJ!z!MzQdffG-q7gjgBSLhymEzi)ERS=43m!^45?hx#jf|wcR(loYkbDd3)>LP3Hd^38 z2=%82KV3pellg(Y(lvxLZg*a5`O;nC4oAt}1w9Dfh~%-fAR7=lO@>C680KUzf-oK< z#bTP{v#OMIk)IQi8^ITma>-Z#-sM=ltr*R8Oy}Avjup{NvJ`wyEDkTmi^eE8WJPr< zB$Lp&nhaw(8$!}3m#{!x_j#xIyoyuQ%;QCz!kveL_^n9CM!94`2#5kp6 zG#Cb7!7(6d{FpWBOz||hDh^t^r=>uEtlT>o=Y`^l}37pUao{R zkS|&3Wb7p7eoiO!T5TkkAV6-!@}c^KlfS|QcZn5iXxZEA`LG<;Z)Y>nG^6!-x^+%YKpt9;aU&kAGKJhbQ5AW2;^-`JLp(o!6G8iT2SuAe8SodgnYaEkBfd zIO(f5T$uRDfH)fFO4~Hh2Shm32!8R00-coy;X$5b8g%RN-4 zzU*hnW^49{qx)2*ah79sk1X!}va~wC>~K%4YRjLTIeKihKHjfxn5XR6ody_MS;_6`TeKfwlyf5sX%!Rz2;_zqGQ`Qd9*R z#N~LFBcG)9xra_No!#etWbzs+y3fVd@L1htwZ(U%$Bb|by_ZYy%lt&K&_#^HKwH8A zFaWY|h?~UjmA-tCO9_kXgIJf;MH{9TPXzm;B`$gFuWJTa0`v!0|CC*(+(7U9>qEsB xWDvcIMuWlH+V5h$I~rraRUmi2c61S%{RW$e@VqctFe?B6002ovPDHLkV1kmO1{(kX literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..dd2f30339f98732ee69776c730d1310c16e604b5 GIT binary patch literal 918 zcmV;H18Mw;P)-XQC*`2vNbMM_XyQIj0f9E{@ zbLQN+ckj$@S67x)5F0N^aUC`w=UHo@k0iR7$UA-5V0eVk=S6V5Rhktq*kHh#1~Y2L4Z;KQtA-NsrWigDD?m&JyY~Ga(vOr3^V-OBAVQI128o zj+xwvY0qH{h_!X>makMQb>qAnAWwKcNQ;1#%P7A=Sq_gly9~PPQ;QPY8EOw0wsy-S zMf!oHzvUt`l2~n`a=d6U_+P>8DBl!Z5hbJo@UMe%%3U`Jo>I}eC$2#&iHr2cSwyOw zROL$|gxS zL~_Q)(T72gwbNrXkS5CJ1$Z;$Z^}nE--W!SqMe0a$9c8?FPq#>Bf(=p;@=&YROM~0(kcs5p}GlS5741evbr9rYxs{QQ9kP4fJS`M5TDuv#{1wr zcnqw3G|IU^nW_uI1u$v}=(_B2@C#^yT~6!+_6BRujk9kBxIaTc+paLwN{8;(y>LF0 z?Eo*q1Q-FKQ^;Nlt}>9`exZ@gAT6~gzWp8K%s^+smBYUtoYa_8qO)Nd8U(HkcD92K z&(^R3aOnf|pq*wZ*x2TNbV3>fWpIlPI(rYMxr^Yhdw)8h>o=_yC0`)!a~j%|pV2&n z`VY+5qj~B}*&Z6!C zQ(MFC;+cj?(qiyg*~l9ZKe9DZojONU(8%c~Qhh1~dVvmJR<5BWzny(%zD3?PU{8Qk z=vVTyG8h!N1FWc^75$}k2}Iw6#Pm1VA)o_-6}N_b(Jwz04-&f-SDVKd2lN#HTdDdH?_b07*qoM6N<$f-s1vT>t<8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..f6f3017dd232eeb6d98950c6b5d2de88d729f162 GIT binary patch literal 1074 zcmV-21kL-2P)bjjwM3_Nd7}jCHxNRLOdznvIWMnoi-Q6BsI0SUY?+YkN=WqhUo>R{W|b%1<9VE zCYc}Sd1`}wGGZo?RrEyp+;O%RDv*1gCHO!@XWx8Ip4>J&4#sK>7P>FViaNC{WA7?j z4MN8xWuSGa>jh&PWDS;>Nu|%q`#j-pA18W9v($w3Ng`2OB0^FZF$5fJW$G{Ae;nqEP?R@*J#}*1|wWzp5>PvBQ_C? zDqEn3HS%4I2jShn*w2cjfuTuGir*<{~DJYNYjZuW6O zPv1q*YKaoVS~Bjpu;m0}8kVWa78y1IZBx1;ZmWi`1IsNhFNSase9tRn1Qt@uT8I`G{I^18vi69M}OY7=-mEo3*55U1pvCIerA z>|~MvHSPMc&!7hA0N)Js04v*-)LT&=;q8%p=Ff;EG0Ha$&xS9PdWy-1?lQK|KF|)Z zg`9XF<8z>ayH5&#+SU88()~cE^2ct~?f4!qsDw*fo__G+(uVSXV9 z9|ztJ`Fts!=6g=y8-8Rdy#=`ljs_BzT`bsO2=G^e^WZhG_LjjCLoGi350Rr6{uyN sulVjYK8PL={eAh7zJTssQBRxw7pM<{i7M@q>;M1&07*qoM6N<$f|m^YA zvt9%xgb+C}2_lFvL~s-p)S#EmD#Ad?Aj%Ac>%INHefBO`6BJu-5PcY|6QOnmg8mA6 zz!XRd>>it4NJjD4;AN|a(He3N6o;*#vZWF8kbzlfL$`*NX@sN4{sr!X4woDf7uKLl zCl@n&f;kr_nO94o0ca{TC4G=;(PpY52{_Xy7Z#yoA(=)ixCY#O`nK`;t7=N`814Zo zyapp-C1-e*%zJizX=0JCBM+lQB>6CYg+;Tqkjsk33gHsSS>ieL8|G(^ZD%WL^nw{M z0wm+$m9YwiC+OdxH?xvW7|kSF0{l_sr1J4=M7LZJTZ2jN-nDq&f^jemR$AOf>v21QIEufse9V{-&{mSH ziiJ{};u$u134#rDCjw<02dUGJza=%fgtHW1^?~}443$U^+z>hqE%O89Wx4rXIk=BMc|D(heB6;Z@!ftTV3{ca)^sX;| ekjr+;4EzPH=R%fZcp$C-0000;G2wsF@BBll!B*YO3gMLUb zp?kYiL`w=GMZ5`3M2@JG6ey`D#WJA~%+x5*An2f8gnIm&o_C+M_SxUhd^2i>%31Kv zT6?|kT6@nod%kba^y}Bm>h=1Ts9`Vw>;l0eQ3#-alcYct5{MpGGO7s{TH>XcER>mI zH;VmE5_fytx~FQZbqmX7d<}eB=s;377aXvHOT>FKLJ~*Q1mk!S2=}Gj{}40fH>J}+ z3`+^dah);mN&F-*8mt%T`GU|%2@+eI3dccw04|xhi+H-kQPgsvDr}$^5HAF6*10Cq zxv*%)`@x|Mfr9bkD7<{phLF4v(O&mj>lEM>&9U5apl~drHk4aU3Y6#}5&}@6!z?yU#cOE||&xbL@U~t)l zjoch-_-js}d&vXdxaNV0XW(B4k62#ciM_R2ZH0|X9Syr6zDGB!RM3~abyt9k|LT9z zoklxAW>Z%-M*BP{-K1({HnmxkJ+3r=B`qMg0bB(u#HU;)hFc;5_Mj8Qe}Rk1Sp0Ju zE5If=m+?JZeSRisMasc%G>zX){$Z@I*0cEB_Kw+Z*Ocpn$MNbGko4SWWom~e!~*mBSwqI!K@p@}CD=oxpygx&b3oReo9R%86q zl)E)CGp)4Q8o5(GbBW+{=d|=UO;GwIf*T4hfVkhhn4G>TvhcygyDo|Th&}`pf#**W zf6U!fzSO824$+0C=0#zjk<=~wFz`=NhuIOJ9qA@~scC5t@!(P_>Py~TSAfr4hpV`O zZku<DcJl3GENFaKR_{yr<#p35q+frq037b^9U?tgHiNNMlfXX%^Z=4=1FDmS zJ5E(?LyqD$a8O;${=|O-=7B{(3-d_{>+j~9k$VDM5s7^v9;8r{^b%=a(5pZ|d98qkABM+N-@FokD>a?!}^WYh`TEZJ!qZHKeu^lM$c zzA`>_x}_`unnTYV{oei#v}T$dxV@6Eg80(NA4|B^UWk7=V@ z=czL7t9h9s8<3w3bWUhwKSSJCR_nQz@7Ofbk5!#X&w=B7gqhQ|H!SnijwY|;!+CIo zTKT3{SR9Q;QZ*Nh0}li3iz@4eJPma3+R4P36BYfmCEf!0{e6a<{_X0Z<~Y7!VR1CL z7e*U*a-z_?`vqK0a%JKDB=xOM-{@i{{6u1U>tlZp+@rCXw7Qb%O)VRBrHwlR{AI3)G$t zmfr`SKSZz$Y~nIkZeE(|<9P!-1O|W`H9Z0^gZMA-jW+75`xi=Fx)!K<2h{)o002ov JPDHLkV1l?hRkZ*B literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_help_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_help_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..8a04a4d870eaa40bae22dc4c61fee8c0283f735b GIT binary patch literal 1145 zcmV-<1cv*GP)~LR$r`S~u0*=)_8InO!o%-s9FGjoRxD`!y@jV#F%*r5PCF_|D1wGIfD1X2f-jRm7YS5d$~ zwnQHa4%bHm23;^#s9=Z=x?jR1=BkC+=V3B#sQ}5%wEP)&p0#dNK`1Wq$+d#jAbna_ zBaqGWah;ecd*X@t$edCFC84K{ucV3*+ziBjo49F!SR(8d6J$^Al~NB{?8V~ZS7=?< zi_@$`h~P(NZch{5V=)eMudWid2h0R5;8Cy&^n=Qm+0O~>YhD0%%MVRD#!ZTOO~}cM zsN73HjTXXVL8BIs4F4zMCvp4m)%bC7SwplPd>o1xKMQ0F6o;>Xo=}t9R~PI%YxGTF z7>&+qpwlR8Y7h$S)WcAIpI&Fdw_c&<*dso!ifQmx+@`RMGf%au=J#n4*Xs+rW+CZ^ z{$%b`M%-Z4z3{6*>sGgx>ELT1E4e3SHb?j?DDKesQ^8YSfIl9{nmv}u1zq$!JjVQx zj;fHrRq$nI6Hlnp3SM^K#?3y4KXl*g#A!Q<=lA2B_5sW4KlkCQfuHSaMzh{fMXV3} zr5Jn${1N6;eMBALxiHE22DqgdJPybn3pKfXiq5Ih8jX~X?afsjiYR&^E{&q$aQqkp z9}hLTeF_hNvnqgPXL1)Og%tl1xA^~KOj473Y(3sn0lt>kk=(^ep_+LN_x*6}@!YIp ztP?Day(rq4yEsiqlP+ttEiL~bR`V68c$3eXf$yb}oNfs-zF^xV5n#Ql;jOPcj-T1EqZ8Xcl+u#S_w%8AV zz*iQ$=&_oZW;?9mb#KIYt;IwydOT#}M@y*<1ORF&Qag4S=m00000 LNkvXXu0mjfANnMW literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..d03a13e2e7fac27ea5b1864e2c05c87717d7a316 GIT binary patch literal 1055 zcmV+)1mOFLP)v2!#(m0dI5PTMekKP<^eL@ly?>Ol~&#Ruo413$V1kz}#2+yP6d}#`<4i`TWw3|fCO8Hr)JP$JiNwzb zez8Y+tlB8OVBbSBjQh*~#VgxhuB|7mq4ef$K=pG=KG}y5cZ1iS=X!)wfNXRq?5CpF zuX+t@nK8PSEU|bjwn*k6FZB0RHYg`<23laY<;8Xt42$j|8!FdggPsMP!d{U4Z1|Xd zFIAk$&yZgNukuyH)qi#cxcGa)xIrzzfV&{H)1?Q}y~if#qcu?j@H33-DLjyd%ht3u z*#tk*YWX*^tzK{9Mju4p0J^QdMRl*`dUWr=(@;dd2*~si`~@zAb^neJIbD-Q5K}lA zOpO)l>K0gj!u+8`y*6c-?0B*QcR+0~Ow~4jc2q zV^GW(a1FcxZ9sO@pja3FYN1I8Th$SoH-?7Q+s;j_R!U(NhQ{LHLHsf`6XqPaaGi2gTc^_1or7=Gz!Lu1p1z-#l< z!W#Jm;0M? zaC=^VsT$L-+X{X7g#$ICss48(o<5NNkLwI?2QqCed2mXdi|(izu;@pWRMB8bhED`P zwF-8)=sdJtQ3oH2qCKT`EYN0)=xiE2O5^pLM0i*+N#vq~3y~fbWgVp#Ez-c?CBUzm z7D`%6IEUi1q`-2W3-#Pl_z67vi7p)OF+;Wyp9LDG6IK@p|2&(>7Xv*7yZ~;?3G}n1 z&fy=8)Q6`Pg!if*g7$L??les?$HsbqOuvh*%Icyv9y9}eWe6+5oGiU~>gw4KK7h!w z^fl*v6ZV-`eIpZAWDQ8;(WlWNr>_^T zaJ<;<$~lf(nJTRcE*`p39XD8VuJ{RBci&ibBSTs02uIgT7akX;vVY8qf{MNuln!Pj zU+8EuQ_2vipF4l&8=cSJ-p>8aSH!u4`M&w@w0+i}_wM|@dbM`+JO?m5P;b~6wR``j zxb^a>?+Y(5rya;x8}_>|UcT)>UV(hew=ReKy8=1|1T7Oq^fuR}pS!;)E_x#ehpV0P zHs&0L!w$K*M=tGUf5YA%!Wrk1x4GW<`E}pAd0&?)-1qmXb6KV9cqcvk$5xdC0uro~ zA24&QRSDvD*pql7-BfShkIc#5vGXoU{acs*+~A=1tc*wVh3yaB{cAaGd7IBi;Tv4< z4t`FGeJAqquENo23bsp*@hj#}VRkKhq<8Ap&G0{`8Mx=@Z~D0X@sT@mO-eyNEY-!l z@;@A`xm)-cwib%jU0V6|#%A_C<*s#)*n_^Seb&$_e>W#v>0R2Vw2lvJJ#N-7JoV2j zrt5o?>&r(uDoYve1Uz{^Ga%dV!AE#`@CKokc45 z&%ct$xWjMuy}$HfnpUB!&W6dkm68YkG96L#I?5qXfA_?;@(=yXBXTw6x@5ZrAHFsE zd*1Znowm=XKLkxbEB|Ag;8i|`oz+*pCaW5*@cg5=d%tq_tZ$7sUawOSJ6E}2+g{~I zTR3B#Czf}*u8(|_?Dy3D?tMXd!Af5#VgB_ukEL{;w^}$^R`A7w|CSQ zJH6M)54AnJt-*ZV${kG}xqdct*5p|xT7=p^-{SV-bh$0h&ppB2T_#R0Z@5(-&u_?^ zod3M|+!Sq{zr|Pf&-9qT3|{Dj~)KNrUoeOej*wAgQZ+rF=} jHB+8{wrNDb8!Z2ryjcqS3J&y{fKslftDnm{r-UW|o;7Ah literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..cb49bf691ad6ec03f982e9ddc23a1e765d7b1063 GIT binary patch literal 986 zcmV<0110>4P)p86)DtwZ_~?;zlvK z6}i!r{10+Nq-Z!OaWO@VG$@}yUX;KzN(TEE0z2L$$Q~h4PQmI_T&9T957|%gO@TLfUgYZfj!}OEFQI%m!_3*NY zKT{Ih7$SHpDX6Hxu1D<~dXTtnye+)0zDrbJI}#6xkCo!!pMNmFP9S>}98Fm_86=aK z;S$wO7b|eqB=)&v;=^uV#Hu02!_&8W8ON1N?4#W~yO$zZOAu|)=bKIN7Q@+9FC#Vt z+IdOW)wHq8U?j)&}P#c$dqAuou|P%;hQx^(Pnz5=mAC zOQ0=_4~JrEE8yf4e8r2-L$7;?OnbW(^!Z#t1TLkEh@DTz+wMf6luhH zhyyV_iq`oG$aR=}{wyIi8)An~$j0C-G`zVsmhliCf)|;DCjd|1zOOy0i4aNIsvyBh zz?&zs6G}GIN&3AmgMRuwRZfh;#Mh8SH5lf8RVBoNA9{C2b+t9DTS#|Xs=p=GPw?Gb zyo^MkppzcFq09U`Vk}{iZo^4?mjP0@pNF`|2b zZkjsiwXb-WSAz4{@K?HZrP_$=UnyBNT|jI!&P+T;(|PraIOK!+RxfYoEXU_h5*!D* z)~M~XG8|uBajeYBidDjlGWzxITzJ$5W~L@r?`G!h+&3fI#`)+0dPm*`_Eo0eJ9Tqx z@eQuH$=lyWRi}FC^ib1g>g+ffnc$TPf!VOHg7v2A2VTDcR>51aAGCua(|?tNU;)?! z)&l$Dze9U7*Q?L?j0Go`Vdex_NGItvKoii!?=#>%{Qqme0Fn)~XG<2BfB*mh07*qo IM6N<$g4#&llmGw# literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a9ccb6bb68d42a2bed19972bc02219394493f2 GIT binary patch literal 1332 zcmV-412nE7#FdiKx0H*7O)btCejF<3DOb>J+U%&6jW3i zqKzOV+U})iV`~hZsM%m)VWLJ!7L5TkF-8K2h{xxdJKxzkd(T<#{IbuH3GetA{YJ;d@(W>`n@J?pj^c0wW$PT!w`Wmz01aeObDvWj+0Xqx*oO%Of zKd>VF13pqZ8{=T`8*$!2J_K))g2;q$oH^2YqrzQ(pSc|>I9_~ zi4Gg;9i*_doov`%2`MQ=sm(_GYv?Pon52st2P=Wku~n1f?!xuM)-<1jXw zHPqd3`VN&jQKwvCVN<>c-Qupcx8V~|T!(j|M~yKb!gkQ(Stwli+l)fGDTEs%Z4Tt6 z?DPCER-A3GIw-P<0Jow@M=i3PL$|0frt1nj>pRMH{8<5X9|+wg{%;;G^BWkstWn;$kj+Zo|9eu9!riecFaap?c#W6QJl9@NLBrb z+#P}Fv)Mjd*mh$xPQ=4F+=Jc+zUsVI^aHsaorFA){pYhkje5S)AX%TM%C8ZGJeU*X zG7lC$}izmqfr(M+ft;LXs1m$T-bJ*kEZLYD&?Y=Sy#*nOT7W8+wDLt; zjBw@KDT;;Ua=SMA@G~@$7LycAN01YlvAiRw?1Vxi9gbzr`qH_A@pUyK2GoOZz!J8H zx9wVuoX+>duZt0VmGzJ|^}n>-F^zn%(TQ(4ufjR#fp!^sa_-G1XFPdkbNl)1|HOD; zp7~3E1ENp^6q$m4_uYU2PnT&pSq9VI48MdzS%1$MM|%=ZL-PaHwfMq6ydM$lm+fo~b#ByI5X3&QuyFAAILM{ol6 zZ2+Zh?Ip}J-#P*7$J@-|#z5K{1p9*K_mGHphR4vqOP2Yc4^Zpdi(U^d>gtEam9Wls zW00?8hy4w${~-g5`7iRW_<>OzBfl8U3ku zgJNxKZaenntT}J-ve(?uC@HqsZk@sZpYGO$=iECC=-)W!th=;xE~b*iDd<624%V;v zX*d~iO4@7lgeW^Lbq3IQw$c_Z`seZh8|NJMz1fdQa09K*v$Y&pn@&fgzLo56%U=^4 qgY%Ol4ecku_yw82#?*lP}WHWXpEPx`&flPP@4e$c4LRBml z`%L?HjD^gE^Uwy#SSz9mDD2Y}QE&*Hgmy?|Er}Aue}Kkkq`WYSWu{~N1bE>J(&{xxZl@#MVg_nQX=?|J z*g#kX=imvvgJ)j9gf=ZOfDSS3(y!obU04&>N2#aNXQ{{+P=@#vzr~<^tfZiu(f=T)nh zY^EJ%^F8({FuuD%Xy$`Ee{?_wo;Lk!;B1cS#qEOdB&bKg4bWGx!R5IyUphZgi{=)& z8ZSSTHt;Uduk&(h^7W_N1)Y?Vpn0Q ziFN0;89|Hj<+hvtK;s8pCY%PZ;ZJrVI4ZhFfhtpEo>dV)W^yGq=lcl8f-XO6cj#P% z_cn;X-yay^kk_fKUj;Jlr0`39y))DGXMRM9&ZGUP5!K@RCoTRkC^LEOoY7H*i08pm zqdjPK#M42Gl&Q`ToA2}q4hJXFcAXq2B0&5sINN761a->qga#*|)xkI_q+4t9*KE%B z5zIECDnAi&(CB<|cFCp*R=R}O>cX8B(&$9LZFFmG-uDr#Hlm|`BIKaSGP=h$O%}Osvyh?`4)(SpU0~aJ~HU`kl>RUl0q?_CL;S z)sX8={)Tori)r%ueiQiNAgtV+*fv)N{eAc3Kdl&WwY->WHBC_9<|+#^}GXbBgOp@WI^`M(bu}XKjuw12Mf^Y jdLQ(g`fx(w|C;y>j!zcM`jgl<00000NkvXXu0mjfrTHC5 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pin_mini.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pin_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..426c3b7f33e4f016592894f401fa1c39c0b313af GIT binary patch literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RYSkfJR9T^xl_H+M9WCijqQX@Rm ze0>?TfNTy1#`a7G79fieh^2s-fq`iO6I?`e0W*RPlGMIzU;t*K; z9Dn!b&*$_>zIxMLXXy*LUgYT8(Cjwro{O%UaYb{V_UyDpH=a*OyBr|(+trus}u`V4qLhWa#otxA7YeAg9`=uk^%R6-*1vTD2|Mr|!>yp#2 zPujhn_smAd;V7$B)R{P`)%%q%m_F|+VA9$aV0Ls)=Htnco1dAqKKS!~#rB11rYE`L XpGhCnP7q6(2nrQXS3j3^P6L!BYyw{XF*Lt006O%3;baP0005pNklDxx#ZAitsaSv`b_$DW*7@Bp-ZGS~p} zXxE61nTipgF~uV>5@Q9iF2%HnDN~|uJEPx^8qO#tQZz0AiB%A5QcRWD3U~!!t1(G0 zMhS(;D2RAOjJ`0|lql69Wewm)j7<;)CPDa_scJFWvwuDZHo>TlIq?uiIz((6Xp4w( zQaB*#_uF254=sWw$M?jg0Lj&tAVfT|aZ7H_VxGyHI*rgmP*V3y9U9l0^s#d6+wfWc z(U=6eeUIp?>w5KDdc8aC9hpwqPLT3}f9_3pGHb(f=7gyrDLU{UI`9KdI3!tOGx)Rs P0000qQ)QUnA=(pYGkAgCaSs3D&$%*n8Bvb%S;IgtIq zvioM=y!Xw{yq%#@qedGgwU^hF<@F#Q;y_K~wSw=C*hv0HuzyO7LbZT>;ojCNFbv!S zMx*w*BuS36jiFvrMEVWP=d|Cpi{t9c>W4Z03Z4Vv>&(| za-~yw9#{l6_X8+hFKJni1bY&gU9Ur(K*IrMEZBE|>7q_`0j0l_8Q@^Bp8=OMKCR5X zR-kLZned!e(|=juSH@=!SOK2rM(E+Taavss8^>pL?;3tX>MnJ#PM`zow*d1~Jz1t- zCqRePM`849`HZUXqb>DH*@09A+O94}iLR?j#%GKAGV-}y<;zw98c|>693<|Ccd5@n zu-kg7ZmI)lP<?cAC&f?( z=vD%PDHLkV1m)``;q_v diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blockpanel_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/blockpanel_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..e5ef73a01f2287386860f275e34298c8615e0675 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr9!3HE}Hf~b~QY`6?zK#qG8~eHcB(ehe7O4@Q zX}-P;T0k}j17mw80}GG^(k2DOK+Ox7;3A9*nBivN zwynD9oLy-Q8JXwH^lWy_b^CGQ>$|tbzlzv074CjmSH^GWJ5N$%N$j4Lmov@%BvmK%X&qy85}Sb4q9e0Q&=?y#N3J literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png b/TMessagesProj/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..d0be7ed2d5f931b65ccd4ae95435466769ab759a GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^Iv~u!1|;QLq8Ncxsi%u$NCo5Dn+G`$IB>9DTzl+Y zZtg*@Gx`TrCWIOtx^q9UWbd4sEB$JW^Ol+pe zT4+6ZBl6%kBO8weBQqP1gh9fA2FCeawP40#K{K{_(a+_#Jm1grLy7U)lL^;YSBm8v UiC(o?9OwWBPgg&ebxsLQ01_`g82|tP literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/map_pin_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/map_pin_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..c9e79c14546657b97dea504a0b13bd8f63003ac5 GIT binary patch literal 562 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fEa{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bGfEmFCN!q^@OaLlg>gnPbVj=i;lC}5Y z0FmSGO>2*8IH`-vb0~>;3AQ#ZP{>-^y;-kmwzp$RQQ#{D(JjrgB|;yCEi5@6J$Rth z(QRSzW5%wZ89tXxZ12@8dY|z9%vkkM&HQ=&x%czt6iaaLeC8ci_3naKYe{-+qD*H; z@MTNo=$t}6VPUR41qtf}7JIr)IXkuIslkJ7+n@Jq=Dj@D-N46u!t%ewi}2&;uJ4d6 zalGC0c2;1)LWa&Dp1QEJXB9NI9Ow~0J!Q+<{oxPOIj^TT<`yJLKH4*T^{W?W+18)Z z>o~!3LweiHlYK6J+omT42ezsuY?l4EqdszfeZ}TWkAk`Q&O~fqkzu_hbmzKk|Mz@5 zbc~m5aMD}mE?T$b=+C^M#U%Y|Ij~|(h36TyFyG@cyTG z>Ft8w8B@v+vhmu*o&7tl>0+*7P-;oN+0qS5jzvkQ-!RDA)LHPbG2gK4vOU{fsjtt( l&CYFLWh*`6$6BNPf!`)%#SZU!K1EQ(dAj!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bGfEmFCN!q^@OaM~9JY5_^ECiDiBv=%qHGlm2T>tp}{{P+T?|&Vw{rE6`Lr`sH zT3d|yw)Jby^z6O!rswO9FON+mUTE#^zyCkKd-lhxUT|IGc{x{ZGhX*(q{2V1kSXj|zLpWtK_N@ma?20yk>M#_aD&}d#EPM_@rgs$g{KKMbJ&`b zq-QMo<*@Pnilb)~j+|vUreNm5Gv!XfQjQr9D>93WIpUn%Royc<7#LQ3$$vYwv;RFP OG(27XT-G@yGywpYG>@17 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/map_pin_cone2.png b/TMessagesProj/src/main/res/drawable-mdpi/map_pin_cone2.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad32c3a45c11d2a1fdd0f4930a6221a4cd41b01 GIT binary patch literal 1539 zcmV+e2K@PnP)&bX@1mm?5su za{)5#{&PlL>L1iV$h(+dVjc+jJog>qzQCC5;AVqW0zu6I)5j?kLYO&X#m;qNhmMVC zZ-Ev(uT;@NbwL2PTVig0p89%w2?**gJ7V#=(m=?Y$J@Dp(1R*e2}Vam5KFgLySLZv zMz4p6!b$SWBv;7iKcFE%Czqz!UoH?;SI8hYSN%@iPb&h5{$a?KUx|^~68WMUk_JLw z^|hw^sSZ8~tw$rtpl3#|b+3~2ZW>c$sm28evOEy9Nnd0aYEWzSL2>@*DKRlgnpL z75^~f5>_p3IjkW{#cMLG^(sZiU?Dgk(%~C6G!Drek{?ox>xs^x$*bwKDf2SzxgrO?6HYsCvm-ky!~ zx11qN;*ztpip$mT$OqbD3ZsZ5{{dr?4B&x$NjQ;Ek<>uQN|5Fkiv0`cTXhEW*!96D zroO)X-0Xbq5ey928_BZ)LDCh>D}$zidEzz#GAZ^$kTM7vUh#ILQl)DSa;voMc1SYW zp||S?bfo(>k8yab@%iEm#9J=n>>y)6(9QXZM|0c4m#=r6iKW)+R2jmOuB0oWR=YQw zXim2y%_)yf<2}V0iF3hcCT?6uXk5pgZ8ohRR+DTjU%Y1H7-RTA@J~v` zmx3_6Kt!A_$?0MQ@r`JBAczeK2fF>sMo3Y`v!$3|^m)O1NzbzBMRuVGH2ek>%(Gtw zi{SYdC|CrqNzZW&swHnu3VXco?x;eooymYWO#w-(X(;+1^r^8;Jjk|9jQXX6Lu z(zE=OLTpleUW|axAjP`)bI9a|g%|}*qZ_kl2h(3)jOH}Iq{88o!&vrPbgbnR8n$zJd;A943S zvBw>Je>`x%zZ}0kj}AyWdB_XD`8Aq(Z*28PK5*L6`sc5POK)LJJE(0Lf-(H%|1Dnw z`w#4qJ#glQkLvFA#tk#i&O|hIsqTLKVqx&Y@9xsXPwFq_C?3;3YRjcy&AID=!W4dv zJ-09SFfy~z8QTYKAF%Ey_u=1mZjWD{w7Pa+TOHyzi9Zh1&0La`2z(nSCO002ovPDHLkV1gl8$S(i@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/map_pin_photo.png b/TMessagesProj/src/main/res/drawable-mdpi/map_pin_photo.png new file mode 100644 index 0000000000000000000000000000000000000000..5e58ff0f8f55e9b068cced60124ee45bb4e12dc7 GIT binary patch literal 1908 zcmV-)2aEWLP)XE?hlUl|L^=hzu)hid(N5bnKOp`zdUeOWn7_OX)CIC z$U90~ai6BQgfyW-Q3*#WM^mR-oe2^_u=8;BfH(c>~J{tSh&w~yvBQY zFQ4JF)FJBDn$L;`MTXoy)}UM}6++xrnvYk&(%_$+l$7j*)c&eW6xB;eN8*4VAB ztSiMhGCkCl{0%6T%71?5;NZ>p=S zi?i8m^N|9mWG5NO0&u@kr)SKV3VyDnEYi-Cg-rgUZYnJ;eFl>NYoq}x*-I8O`HH&K zwkIYg-cwQ%sprWAaJRPZn)?KgPE1UE7h7EknBD=9+pEnDJSQi|5)%_spet&?faxaL zuzRF;m(skiukTi*rn5i0dwP0q0oX1T{f8sMn>)Y))RW z^Pd;=56++-iTGK(5^TB*H=txT37U)|;u0^`tgOA>%cT_Nr%i564;i> zC>OVg+u;>n)TPL5;`etqa0f2_qf2T)VJV8)Y!`g4scy%l{SR?LZ(FO?`cMX!qAtM6 zY47gt{#9?lf(LBBkx?9r?wwoCTrS`%gaM3llEe*q*dop6F=TxiEGsAnC=R!Xu+Ko zDc8aBcXD#_6|$j-rtS7RqZ4dcnA;i~8*Ao)9t14+W@l%&!Qyi`&eT6wR8({oBb|s} zVg|!%Nl8g2nNUQt#_myJDsb^VetdlVZlt8MlAXxjZ^$AuInx}+M}!x-O7V1IVPPhI zYks7pRO{zq`*cA;!Bw)zOg_PJkJJG$>T&Ju?WF*;X&usweKy)o1{AXRg~mP7O>7VB z1urAzo4hF2^r^|o$?s^p%;2+a;~qDmhxp6Gd3;upj_=7d_ob7P=V>dxedD4jKmR1d zv7(LpoWci~CKoFzD)P3sx2KdU)5>|+I8jzsmP?yu+XIHibCNJkon5)7m*V5&Ge<^7z6I>zX#unD z(b3VS*w|QhWK3@cCZy290|K6H{sPK#ZEbC3nCm_cH$0l#mn&HFYl#+fq^?%uUk^v0bDTb@9+OID=X^-)-BsWTU3RHey7j@d`CWo z!qHJ`Zf-cJSi#>U1l=Ke3@JUdB7H)3I7 zyH}wTm;r>pf`6m<0{=qwb9s6BD>!DyC_b(aOLW6h37~`sct)1#&rH}w;bI`yy}d5~ z;(W*@+~5RYoud77{}4rS%^TNLk<$Pth-bY=7Wq}7HIy12Fg##*!0>?K0mB1^2MiAw u9xyy$c);+0;Q_+~h6fA}7#>jH1OEblF@nB*dkTR70000hLE|vaO^_?5IT~6Dq+{k~~$C>Xk@Hq6-$lEZ8qd zf}K)Dd}usL;FtPc68Lvj3^xZhs>GQBI%!)cHbJxscEBs}%L4oyIQ}N}4kQ(K>$y-s zI^O`-nw;J2ywD`bwI4CLEwCE8dZ3y^rENExL~8{50qu_wDaXBF*J+?#srNotUnJr+ za=sfMDSVjV`zZvTqR;6)$Yk(8!KJ<`L?k^qC%rg!yd(M@Oo4kKdGxI$It$-`6)=(7 zshI61fw-D~x#mI4BnlSEeU9>Uc?nAUM$o@WP_jusPw96J~!*ofGnkPwOoJlr$0XE0kv(<|YZUODnvCF^W@3e$xP0;jN*kImX#E$ze z_zRXt>K}@?@ufK?<*1l*?xK-ly)J?EPPG|AH}Hjw2Dn}<7c>XK<0|_@G<;AHctvQf z%eKCev6@0jO_MuuO`-Qt^2JXTtFUE9UMx=s ziX;$j0?je?%;!M{oFXqtpVMK=TUhp?h7dM*YJldjNb7{B3Ydi|ZaA|JyQZ<3V~FUj#j%Ii}U~98~jP0)+jEP)buCy43M_%B4txWRpl}C~#3Uc#^wgR(E@R)LDEgG-DGWa}RHUa9 zu?3KCz^ska9{vf~G|pbC#?L_)$!_oqn07Z|mG$mt} zdf-lMi7iFs9)gJy<0D9!bG;lfU8tn)=C!P{6CC-~ zUWE%DO&yGW-(j@ctx~@T_Ve}mBYNxw5Awna#;Ub>!ey*x2AqOtVO4R4nh!wswpfv4 z5w1FU9Dl{5n$dJEc3&g`VPI(HCLDripWG+yx zz>Sh3$q^;-?!z32RrT^U7`5|?ZQ-L9GHR0)J8O5Axdr*esF^sw-;OPQLO$MZp7>N8 zUkL7naKZ|R``{@&0r&N7-Fa%OZV?CM2GxWO_%*Yp@D6^!D)jgwa^L-2a7{xI>~9d% z?sJiCZ-VR#tnX?(!sDW`z;8c!!Jl5E58xJip>$9fIO_h0+`p= z)}5!|c5+FAtbFphA4V|kHMFzV?^FKaWKGo&@<+iuoa9gws|nkJF~3OewV%_p9%xVj z-vUW{%VMLXDU_h04PJya|4*&P|0sO)4szF^3$|ej9&vSj!0+AIpbln1b`R{mbe33m zlkDo=cZw%4?6w&hMVFI9$#uo~QG6rZ1)ZJ#q^_!%=4E)}H)$xy-orOACtW(?cDU&G zlwBk41ldqo(azvAXy#x;V(eu|pIM`+U|K6Y7BsD}3EOZVj%5xEC21N4S#wBdYv?Y) zCpBQVY`&sL{J^wC(aDP9gn*vYpl?`6q;nwp zSb_=8+AF;J$8p`P&HbcY)y5G0A-MzBK{x#&(5wFtbmLod|DvkiWH$}$qBEv%`ETqG XuNgUjtJ`T`00000NkvXXu0mjfYKTR5 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..1aab19c561caedbdfaa2b07cc88bdfc189a0c7df GIT binary patch literal 811 zcmV+`1JwM9P)#`hITS9&sJrA$-N&#se&7q1{B6_W zH2nlUNn`M&y1_P%i&LQAV*#GRN7xAc#JN}$RxbRwBw`Bs-~?!u_JZ;&;Vb!L=u8L< zLn({YTI9o(T-E~Ub~f1+YsvfAgOKe7oZ=Mg%4teEU__zng%~4t5H`ah(EaRW5q6nZ;Ll9$S&4|qL_-I;czi7o;)=K-}8!H8ZpsG%MQ>HjLm9NOoH+ zj^nFo$bD)H7Nk*LGkl->mr!UTp;v~a>1(6VSjW)}H_0C+DhY=q_9NeO#A}@kmwdxH z^eVXLeW{yp-}~Ru`M0Fau$eY8)fDT1l@tzHd>u}EpbyT&K(RCP$dy2nyQ>xJFJ8EpkaDsw}Spy p=-Ab9tP5;_PcWW;dEx(i`2}}V(oh(MAh!Sj002ovPDHLkV1li?oEIE85Eq&dWFtXTfS@m=(Z|la2E5@X@9*bw^ zS#A1+;w32PqQ@Z*Emk9zy@DFkf=9e>3GqDWhbf3HZ#~XaSshicNF=X{w4*kV^F`gP z%kah*q#uJ0_z0U}Egaz1&B41Bt68zxC52o^*l&64(VOD@@5QXFQ~NVxNH(|Z6on2~ zPSas)Aa8~Nm@qAP#DmZ;0bdVad_3j-JG5%W!4Tetgn(Q(bt4qp($GhxK~)L3({Rbh z?zG6Yz_~DB0pbXlxlKvZ=Y>h@leZ^AetM%M$pm-)n;IB$I{CPAnVy6m{9bThghWic zu8l@r{9(`zIF3Jw){A$mZ9u#O+KD>NGp~ zL5nWT6iCooLFT?9yj_WAbV5SEDY9;;i`TH5k*K)3m0LO^Z`+{bJrrIT~I<0 z)WTXwt1^g)f}$4E2SJNcXdxs)8wJ6ljc6eVl@wt_Wxd<)f1Pug_wJkLMK{ucpJ(Qr z|2Z>rKi;*fDr9jSpDfA|SWy(nIiYS{SW5N_)WGMmDiT*=dD*0bBx{37OGHk&2mc*v zpe>4`ZpGC?HVSRfmjqp+%lRiH3TeUxM+nA6L6=bcQ6^CuNOt81sj6mv7MfuSF0xDQ zxV&i{WpHma#y+@tc3;+FP8S#OYn^z2@e$|)?I3IjTHvjOAgf%UR)~H=kJRDTB^k7r zRe&XDDoHPFTJDnXrByqugy&rD#}!+%o!@XCRzoA4g3P(nt3qxg9eZIAzJeb0X=o*P z3!gO-$Ke=^S(dTgY&A(OU5SVu>E;f?K8puEqQ9Vv zaUUKAg?<9zIP8D{KW=0HOi2u(u3{71fR9OVzCRRQf^E{_XXn$WdBkR0(%}Cw;9Lh_ z!p;})lf;iM_{0{u;=hLikf}4f1-Ly@y{Q)6*#H z$XlOFN5jsfZ5$u80_Lyb8)QB>rt!Ugwe#4p6P=^6{wdfFdcR)r)yjN;oVLj2+KpAP m$WF$);S)S#kr~S^8UGI^5Ne?f&ZRa00000c1xYP}mO%^Ag;*Gs8w*NZXhcc9%9?)v>7JQ4cjk>sVBmq@JLmq-IrrU} zxpSwgs*;76a@G1F9+%&QS-*ORi~Fbu;61dZDiIbX;G?y~Nnc<*7bn*ZsQ%#3ko}Ls zX=r~3pJ5qx6c%qmk~Lg{pU`N3NBj-yY@G5WreU9n#AdHeOL?+G&|fa9qkOD5+Aj*o zJ;Dt^E%7gS3C|c0;&tn$h$9OuKiE$}^qX49 zuPWiJ1E1MG{>!n-T3%6j5Bgv~tiTJ1&5oT0Egbb6Jb}}of6=%px~MShAx;eO7935K zbVP0^ESVZ#AmVMr-InltiEAD7wCy(J7U+gwh8b9Z>rh|mI{p1nsV>r)=m<=Lp6EP$ zhfZjLAMlmbA{-{(ywTVSnq&?Rme0UAK2(TxB7K6%@|q3BGq75|vVV{LdSc8sDe3H-*|kYoH^q zR%au2f>?EWURPn5cm{TnYgd7c@i9TZ1euQ}xx~mH2Yt)`)vhJ8ZrA7!_`6{5e1Zfg P00000NkvXXu0mjf)T}-@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_pinnedlist.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_pinnedlist.png new file mode 100644 index 0000000000000000000000000000000000000000..57b6bf7b68b49ff6f5839dc293b2dc7488ec649f GIT binary patch literal 604 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zEa{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bDfEmFCNxGL_n*mgO-qXb~#Dn+k6mM;p zM2X|iJ5m<^WGXAtH8V@wQ0O^rO0VkX*;{*qrnL4SFkf&(Lq*%?#8RCn(^@|ZknS0;kkOk?QN`qH=0E={%&2SvF@;# zqfonvjZ^x{_Nbjgnp*dnToQ!a7BXKu*cNwsQ(px0k+2P4oY#Jf_h7m$_A&FidysL@ zL76p&cs%P>B>AqXK@PNrp z;{vAI9<98v!|})eF$Ebk{12#mldIEvX}{qArGXpxSUcAT=P36b-===%(2aNYZ-0tC zzZ5d-f=S`Mz41@_wKUj|%{mjA}>amVlCbVXLveMf?L zL{7;}bKq}I-}C1D!(CHurS%yHakUz}GQFrOmC|E)O`=Tfxl-b*)Kh9O39nx1?DE4zxJnSKS@~8h(E!gWsr*s;s;nL;#Z-F+N!udv(8y(ch6qKMGQFb-kEvlojJSroV$C=%3j;T zFzl0=_)tD}G>Lq6F%b2B@AKCoOlSaC3BoiV<+%l_)TY2drV;WwLmGnmic9Uao(f4Z zKIb;3^vT!cxI=C@`aZD}gM3@o9LwiqhKW(7LwGfws5tln}o8)XwfL?@=5nq8j zk^+7Zya(fUy1){UbL+EZ$nPcJE6p=H^%(yxZxFQ>@K?1z^K==Wh5&2>d4F_f1UUrS z8XzbA1bobqJ=2I5fLO;f`)?6F4N+$p{(7+k;U;iDB{{!U-~h+d1hr-cy0e*7dql@ z3*#d< SZ=wSL00005d{ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..e72b3f3e9d9d132264c93f42c4907a3a1158ea0c GIT binary patch literal 910 zcmV;919AL`P)V%bGQo}f$)-V=gs>uJ3I4cHp`BZYPEVF zrt3aB%0k_6yh7L(OhKi@<1L}hFcVTRJkRA~7=SXY7ahA8N1y^t$yrJY#wz+G?8Dts zsZ>e6<6Dxp;UQcIQ7SMD$^=}6o%#@T9>E$c!C**3*(KsHT!w3K53&qLAGAk(J{V8+ zAlnHkPZ}l?Fc`wB)!z8JP5SNN!heHh=*kU(VG%k(>4tJl*6xb>4KHnL3#681E#MaF zcmo#+8l!ccTm|KKt>KBY1KhYCjkNvXhHk{ZQ=EkGMs0@#-zfYv2x&VMaBc=he;VGA zilQ*`{|n)_xIb3w4|orM=noWfYF!*%;6At?ezg0ush74Fl)+pwh8=MAEX8TCEIm@n z1F&2@W(PB)6E=-jS&VNeqr1t9n;z`?Qs#1e^%Ct30@i5nfF(V`nfgR~9fG7Jt3kN} zU*QYP!82%P5aYr|)7AvzEV#`3umDZq^gN4-)!}V%Ai-QKlW^?mZ^XcUqtJW6h3c^H zJ(DqKm)R+Nr~O5@g?57e9If@%k1c%)-GUI)W*}nijTYREyCmc8NQt`*9=L1JVccpo~Mh5-nvn!`<^NjDupVIrR(v$nPS+n?-TkKY%4r zPeS*mNo5jl9BpYZW5FDA9YYD_V@$m)D3MwER`omh2(MwU79W0vt@JO!R7AZM|AH~- zdti>a<1iP;L@fyML$Iou*5z~NFTfgB#^7^AUD0QZv0>u0tB@<0`WMA_dM?BHWi}P` z6>z3E;W6BT+Yxnb`ixnLIjCWb{2AApgju|TMf3*5|M@Y3{>^x{;kI4@68SM(WUtU2a7hGP|1toBYEUgiFBz0MV{ z^j=7pljZC$SW>xLZN?a@nClq%-*WD=3LS#|$^lr1ZScwrOBZ!*`iwbx_JuJ|>^cyn k-y&+z&u8!x-+qdKe!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bBfEmFCNgn(gJ{_o}$J50z#DjP4R9_FV zK#?}tdas}yDHA=XxC+j^_O^0)^@DqoKj*wW@YwRZ?fbo-&z_l^9TciGr+D>-?T)fO z2VbjrK0EneUT2q>-a(#}$HIp~Z^ZoK@>$h<`h&Dc@duf_g9+DLc0VaQ>I zH)l$JCh=7s6kI(iG_ z4_){ye`4ldhxd)<`4e33zB!(})6&GP=CkTf@h__N>_z(VTB`M;B6_Gf0g**ulD4Qyuo<$OPSz1-JK z`!K8gx-8pA`5(BWmV`%7-gE2vd#1Cew(m3O-}aRE#>v9FYvs7rmT)gv|6A&p%Fb0` z^))w+&f#=4)BS2tIb$A&bNMFuFZGMgOFd-u(VqJA>96<&N4NTJH7)PLwJ8mG}b9#DA!1i?)0`ElCwK5q;>|nmd6`>vVk7NS%G|u)CkWs zUtb0-Ae)1Mu|1Q41;}CqVksbIU|?Fn1Q+33z>HvnBmdKI;Vst0KWoTK>z>% literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png index 68cc22fba96a026eb8da1ed1bca723f4b26fc874..a684b8632d40409dc662aca274f7082490dbbf0d 100644 GIT binary patch delta 418 zcmV;T0bTy~0=ol{BYyw{XF*Lt006O%3;baP0004UNklbD5H7JYQ%t#XyE2-N6AK=+>^fW)AMyeKaY7c>& zdq3nEt3g1%4EZ3r0c33;=W8V-=jB|Hcynph&UK0+k;)wq+XeDE?m-vmncrY9C=2!s z*iyfuNs5#j;D7Jis4+SE9XtZL&=PrtEEb?h#5cg+vk_y?&~ij;KqeUgzw;PZG)9q# zZGhgko+H-+Vv9iD`A9PC6}`f63|6?n7iGh~1W)QW(r(B8h#D2wEFLyNO-ZwG>|Zp; zBrlY7K71Z6wFqQ z2GJ%4lXAgkQKQ8mRxv4J5Tj@?7!HHs{AA@F%$@7Hw|hb19t^YdcILhR|L14a#oqzY z?pP-Ujl`nHN5Ex8MbfzU)+LQfs!Hnp5{{y%Nhe1J;V1#;&VT2LAlg!g?&wg`tfXy8 z2Z=ihM8E0CFMtTxBB|av#g{Dp01TVk=~RhkB<)M8Nm`WjZ2r}kUMPbR;L*`9wEPK+D}3JW-tg`TVyrh<4Zg;Uroz0&7cgNTIAjH9?%DDcpdkAPhNvv zi=4!@1TMY4^;LWybWGa@D;Bu{hRpQ?$L4FmWR^xqGMEQGfEQq_RM00000 + + + + diff --git a/TMessagesProj/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml b/TMessagesProj/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml new file mode 100644 index 000000000..d44e9eb62 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..5ffe3c35f913b82d5206e12b4ab93cdbc91a28ec GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-S!3HFkynkm2;-owJIx;Y9?C1WI$O`0Jq(*qA z`T8}@-gOq!^`njxgN@xNAs_7ke literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..40f767d533619695ffc8e9a1befd128066d07453 GIT binary patch literal 963 zcmeAS@N?(olHy`uVBq!ia0vp^Q6S903?%u>HW~n_KLI`=u0R?H{{R2q(9jSX8tMQ9 z4GqR=AOPfgdU^r{fDB(>UpF^5kZfqEWoW3MpP!413y2#KVB_u0D!`K5fLjZD^@l(Q#Ut8CMKX(CnqPMdUI!ITW4oe2QNDp7h`vK zXJ=0egGeiTCm_S#-pR_z)ymPu-pR?%(b3k$Jy%si z3}{VANswPK!+%C5piWj+Hg*n9E}(6ky!-+Jf|k>7eBl$F`&az1&;m!X`LcIKl)s8= zN$5)IN$G!kxIWcxhjHLlHQR_i(mGBdmAjsP_YIGYPfSd7^Y-=gPg~_)&cMK=?NRiABe;OLCKAP;fMP2LjUZ``lE-?-r1$nLba=E%C-qLI@Ly zzT9%Hp+Zydp2@E>crGOUwchrX^Xey+bCM5i{5E+q2z#tNBjDU(tlhhQecxrDwi7nJ zKb4i1oY~Iv(Ja{M0E>d=5rxFF`Mn7_vwmiI_V_4sa@-I&d}gCWJlolqAE$kp^pAVt z|4*+}_b!?KWm4QF?|9ZZOQHas;j%{B>RQ%23 zH;X-2zh66xS7`#@yI&7xuG^DlzP{$^*`;+cw|;2J2FuCI+2noS+PFjWac}sR7DuxUf(FlARyop$oBK43#ZqGdecd#YtL|; z$@|0gFVdQ&MBb@0RIG63jhEB literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/map_pin_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/map_pin_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..1e3326abc52a5117cf61e5f62a5ac2e769a7792b GIT binary patch literal 1025 zcmV+c1pfPpP)WiS$SD;Kep+R6GfuJxM`Bm3mO=p(mjhdsG^!9u%nsQJSXP z-5uZC?zU+++0M*v>t!EIW@qNTH{ZT}yYm7N2|&7k_EoyCG`JqIh=uJmohx;44y_z` zM+=}g*WiGJaZB1WHiyeR0of@qLBQhU2!j`#^7lE~54E~S{+?XHuno;pHK9Mb-0m~dF9md!< zeE1`nuM;?!0Sn@s@k4kshcStd;9;_Z^x_cfd~-YXl&)1I5OBJ0_5;FgNz_5l%bTfK z9H0#$TCnYMV7_BNrkgO-{-~_YFYqiTw7Io0)i8LGnU2oJb(vi0*wi$?jE{K|+gdXD z=?CvTozypQ% zUQ8j&R+9V)0z80wbr~k`$8U8uG;ZM2t}e96xuY6f&m_1O$BYKZBXD z$E|%Rr~=Y~;)w0b z9fc?PB2xeu(f^3_)!5a&<1qeF2zY=N3tPXM{Hm2K%`d%E>dkk$E~c8jZ;_9 z-=*~j#^ZDWH?j*JstxG46&2DY8%Mv(@g-_*>xu7H;nt}E@>IxBZP12M^Ggp}Bb|ym zf{GvMI)V`V_NhShUjDE0(n}&aLzNpgp#q+CCEa_}l_Ol~2|=iWqq=~a=Pwe@(aTj( v$yv0EB#J;3fhYn|1fmE;5r`rXS_J+9g5PxAMB(-|00000NkvXXu0mjf%3RD0 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/map_pin_circle.png b/TMessagesProj/src/main/res/drawable-xhdpi/map_pin_circle.png new file mode 100644 index 0000000000000000000000000000000000000000..5bb002ab58f7298dfeb5d692a6bbe50e2e689e10 GIT binary patch literal 676 zcmeAS@N?(olHy`uVBq!ia0vp^Iv~u!1|;QLq8Nb`OS+@4BLl<6e(pbstU$g+YJ_K+ zuP=iZkj=rs*q+J20%UVN7+93}6FO9O(*N{C_)rCZ$YTn;WTm?Q_xh*3zlh zRl`JF<2Tt`9ZfjBN3Px5 zEnU%!NY>x%+w2$W=nSKyGq9A5jp*Ved3zM0A#69cV z+>A*d3cGk%4bDXtOWjztPfESB<76tYxa^?~nOxsq6lq?1JGpBs@3Pyf*ZCOd%+8T8 zcVbw4ch)iiE&*QGBTqK9b@MUy+&oZXFr8`t&jr6bXT)49xTx4*cw$D`?Pn*KPWqw1 zwl)f)jy2|RPD9yi?T(2%7aiMJ&mZCDV*DY&%wcz_=no~gKiZQ{o8I}cGu(UWR7r(n z3e7hYx+7nIt$H9=6I9I7CjZ`&NucVgr{kHpzN|fGls?`$_~cmjANC(#?yCliKVw?+ n@t?RRZ_N6s@OXQ0-|z!(+QJ|AHATMs03{VqS3j3^P6Y&J$92)9vYV23jL( zwMRNh^rQ{uhf!wQ2XEl%(BzxCSx7DX?zcNx|ZIXLlJ zj2t-6+u`;C?s#oGZ=vi=ibqB8{8WTk4SiD4@Svj0j7bng+q@+5Hlcb@7yCs@Y~h1u zqSp+a6l#Gxw?R01*jL#=uwJY#s$}ihdPeQ8-4QipqvxC3#li+p+GZ$eSnZo&W1@9K zEBW31T754Quk!}y%p{R$2#XIrZLR&Mv4o=H$J^hsUv;N{-x8UmqX`Yv5h@b*d9PCW zQqd}{Qrqbu8~RZuPBuy-_h?Mee(MD4P42}A{}lq67*YE)(*_|S8v8#s@4V8{EGVfn zBQ#K9csMx{KQqut%0i@7Ys56vVw557GHAzJ*oU%rdS2hcqVX2^^jbzOr!a+6!+o_< z&CDvJp*{?y6BxPbCcE-FxOogXP`-J`qkyYG1waL`*)JoUJXJP3PN)@}eVZnc;Ft0(H4=A+#T=Qjh(JzgQ zVlLjmz!r+n>x{wJ(pfmE+)8y`KFtIR$MuHC@Jr26MmlH+K_)b&{8MyNmxbU?)AhRi zhCaoSeau={FMQEy@}KtIeGu#flpG{@HL|U|a~fcub77->EuhL|W$U0)H@e81&Z*CT z*TlPIjkumU>ToCkEqGqF98xsy7xX8G`CuG}kSds1;KtnsIZW-Ho(%~6(6J86l#Cj9 zi)W>GRMI*;I*uxMWK(c!AYDry&#IUE5oEe3K+2F|TfO7UcBYUY+RB(LhS}UC7`;x< zP%Guqe`@;cT!UX`Ya4$|+(8*+zx7F)3Hmk6Qr4m(TTJ>!%r0tt!F%(B2P2)QQ!)R9 zH}MW-kalT@$3>#liyuJKgwkARGEfmiy|lrq+Y=@%ZYk?YiAHI-sL^#QaDt9fet+Pz zfpTQly6SP}m^$weVy4HqY=(!kMmPPF#Vfay&~4nnx1*#I({)2@R;egx0wE2(EatH)HdujtF*DryJX%davfpI&yZMG({L+?vC(Z|s< z0v9%@Q(!a_V@#68n9UN+B)jXOkBoo_>O*EM(Rd?u>`vMykVq||oLC|xQpsPf1({e+ zFWBJn4tE5MxJVh~D_- zK-@iC86I?+gaTU>XC#>59J! zD>Zwt?LCRZEG}7J=c*-Y(xpDXNQ6<8*lVf75lr<^6U22g4d%4XEW^zA9BSF)Y^1=F zUVjgCt@fH_f&smk2xKT4U|cZiUfKbVY?%G{ZYHKxXWQQ;f_kcjOJME?x*?(WS6E=! zNKF5mpJxC{HVTFO{=X6ntJuFI1^$cVEDEe_!ofkv(Rcc9xe{d)uKNCJvm80+=0^ry zbcBm-^CKgG2TOy0R%;UvDsHm(0{$jHW{c>SuAuGW!jF8mbQ!$gUky&oC1{urR&zeV zeB>^pa39X23C$`?reH(3<&R&dt_vfxn+ZToBrGW#@whjG3UU<`r+4!A2C3EB6v^Rr=PUrO)ic~n>ARj2BD5Bk3gZWg!`db1=QCfUb~U5f+cQ-ZNU%7(8vxQGR< zN7mfmuWfVO{Y}hb8Qqz&LAl#NLQ1!A)hY8!u z{jp~x`Oz$zYUqCIDqm5YSYLwuAz+Zi5E0jEkXbhQ?z*u3rK@~yMJAytvQM*qrTv2x z!j7<27;(wd=e&8HP4MNc&YFbUXg{;o$ZePTgqpg5qx)9Rf|B8PE$6Dd1yhlX-q-1@ zIlir02-c?5{Ogf4E>>E{>G`#;+|63^ZNbw@Qg@cfPly$Ua=Z0UkkjU7Z@IDu#=B9# zJiJHibpuzkY*Kd@YFB&|i?z#eXkMED&K1oG<=H|t^gC+v#A5-0XeIEEYoUB*Kx77^ z6~nyO5_??zjkM1pm}pjVvLfY}7lqG74d@sl70nN(WXCfc@n#yD$fB2Jljbv>pa(6V z{ymm9r}eK=Xx1a!y6y33pD+vwWwTmmJc>FR6!WmjXd-rLLs40Z8uXz$c0pe1bmQVj z?EI+@opQ=V5qa|)aky08Ao7Vn7jRzu4HI*u8Ecl-t$HoG zr(Y?*d^MVZOdb74iJ6}l2>m|n{x#X4HTZQ}58Hj{wMKxzU;;mo!{=96$)5$zjb37a zNKEv5C^7_6@I5!tZjwx4sRD3^pYXSP5gl7%&jrbTwRl!r+u&R3|5ek8vV>m{m!T*1 z?eNDp=OP8F&S2Z_8$}4mk=-x#YwO@P4u4o*k z^j=?#cM`Ltn#^lcVe%vAyNylePbhAJjXt-irofT={Ee&4kUz|!uA53Kz$76AOGw}! zxu2v|771hv@`|NCyo;y+ly%9wNhl~PPk%TL($SvH=ymEz7~;L!jo_|z+3aADGj1sQ zu>_aV8<>AwwW?}jnfA{E5Ma_j>$r1<;O^(B9t1ndDe$%`CQ-pw4 zzZ4renIyj;IVZlb-(OD#HGkfW1P{8S3mEfU#im!Fm40et!KUlX78n5OsJM{p$T!!45Zz_gi}v`>V}Phk3E# zG{5s~Ts+jok3;Po#jLB9IaA=Yp+WX9!?M8aWMGtDW_a8I_O&yq(7WhSnQ98}^eQ%f zC96OB#7^t!xGxJ;WP9}E&jIE8=ZcT8&>_c4jdjDItEv`PjZc&hZS={G#$P-$`J*2d zQQTtG#Moo=lcI{^Nvt^^{~CP^(x79nWPhgPS7vc0@7rIYog9_P9d#TZKY#L{xciJu1RTYJPZL63R&9&7nWF+E`uLqaL$Fx*N(qyuUg=UJzGUgw zHsqjV(qjB=C{9&=)3mw(dM!|@yaP05%kiEy33Sq4pF<$0pNy-SJMw!!(|oF^RGn1r`ndQN-PSzVC@=;KX<-YppZK${>CC6S+R`1r;&MEzGI^k z^qApSy9FXIpb$!kR8| zM6r#EF;LOS{@t$+ABs-ixOT3>B4KGI)=bb~ZSyn`4rI-t*(-E@J3 zQ^KQn1pF^tBpnlw7E|eyt4!*>+9S|CU!Rm2Iaci|$CK50C}OYhrOcu#={tPUe0oOs zq{FNB{L3_Ld!x{hVnfQVS*GqS4)IG7T3;@SoxQP?zT20Sn7%esvlBa$TpxlXyYtn( zDo-TKqK9}D?RrZa?ZlY9a4UFG_ecozAY1$pNwLDyS4#m}66Mw3Z2)j0@1gBEX&IeQ z;Rga*nX^9jN5AUfdLG%Og4lSG$45k_F?8B@B$our77%k;ru({UP3)I+5n!2c!K1+p% zD7-9roUQJ1n8alDk`&17DsU3nWZX353RxN66Z4@jQ9ZF_Y7X zxG8Ag9ortu&+!&o)w*21$!kQfthUbFe(grfCoL975YhO7whpJ_DjT#(AVLol*@ zlv(+KnUG?+r{Kd)p2f}I*~yyup!P7HOQ_vCFw-w7#M2Mu&B`TI2rhtuuACP&`_3v= z2AgYs@@NNsu@21N{UU%piZ_=h4=X2ON>5r`C<}h_nEVkm-$&@&jmiWxzwD*}@&A_V zz`CGiP}nI<^ZN;4!A#N!!BM;btdDK#>gsa5{rej#00s+#!Qjqn=UGIS-~LZ04{K}d zq=<-!BUQ#u5p5!LzKs8;;^KAg4btbKT`et_pY_VL4y!9F=IdP-TUZxkZ7TUUQfP;{@Y~If{B>8+6cdcPoC$(mk)8Lb;&JkYqn5 zk=ga9SbJudc-ID3t9v7gIsD9aCDrLBXPwg4twf-;2v8A;IUkB+*v`Pf!0Nfz*3dCJ zPpXma$IQ;hW%B(hyT$bI2897pB|n9%;1Mm>lB6mwKdUx~0!cQ?!`v$1 zvkb>JDOuGp2(@O_j#A7~l3Sh2EW%=H4fGsN=qyEr-{G>*?!BvBkz32z%+mA6*Wm%zr zFlC{HFbA$-eYa?7m_>yce1|2PVJoAVc-XI|!{vNuG!2WzR(Z!eT{wRp`^joMH9FN7 zZ6ZV2&(~)Ay;ADkueRGi*qh=qH1RWviL$b3ZWoSwsEBNij@L5X#V1hlKM|mQ0 z&{$avXtBHHQmFOvaPf+nN{`*&%k<^#Tbr#ktshOsP{C+$!vrafx~(@zu{VfS+GlUr zkWiqulGhORV{k102dNdyn>!Bc)S-czk(I)b%XzD_xD;`n_u14kvK8PoGq;oH3L8oW{&XqnbLl-Ms6% z2eCwKAVfa~d(Sp&?mep9V!rU!w#pu7kCg(|m-T<|PRmVD93Xm`3zKBF5yl2zpR5nw zTwu=Q6HFTwA1eYLXbGX(#$uODl*U$m4>hsnjycX0U>FdIz52ivQnY&rz3m;#jbIZV zKI&uk=SNJr&g(7~EF$boqC9zYZ9vPXb|dMNDO@UJ=T|Y}uZX?k6!1j&F3U5{`Oo+) zMc?qJSr&^{o2NBzL=r!cU#PYEmc!U=6YUiTK%nU_j#uyS^xxh~L0H6#y71LFyN@B2 z#r3FHPBV-w8HpN>Z4QA8Yl;fhy9nP4CFY-iIxl82Wld?ytqxGK|jxD}+goFprDY z7Mh%<{1aSyCvP9MbMS2tJ4q8<5>kSD{w1i*g#5X{NKAbGx}Wd#JVgP(<`2yhvT%!d z!e|oc4J_aYS?=(aV3&4tzg-*QjzV{|Y zC)J0%4i;Xu+&B;58YwAqcPw9~$gI`vKp6;v1KK%Ns79N;QVO^|rICRN^?R3#?uAk5 zQ=w!NN=2X1DI|REjMNB44MsU6F*$<*^05*FULhB?&@F$xR$~Ex>SylV>W0e%pCM*n1CuNtu&Z|~{+s7+wHZbyP46#c| zHlfn9JJNi@tJoP;r2;=dR_K*wZb&D&OPIp(@VDafAo^z`dtUoaYcxlP9{1^1ywP%h zDRV~0qBSn266GC)=GAnGNsW@$ZWX(ZyexE`7U8n^@(ygFREEL4Ta+|o1Ooa|Mi!3i zK%1yAG~=M>X*PE^tnL1j$0$9zXa-s#n1CyDib_~sii{T=x6ZH-GB6B6biXiQBbIY+ zCmsXbh*qda=ffnQok#-L5$cw`6Q5ObeLKrh{KwuZ5xFPWqh#NpM@z_3k;w@qU#gRK z*oIz=1+qOUn&E!X#h$0y>zQ|(@59jfZFFS?ObeL(tzYD_$}iWCnu3FI-f7W%q(?Le ze9MtRPkOdCwO z?P|xm!;*$;Sy=UD$nn7`1EE6HIR_NfUx;9HTeAD+2?Z>%dbM9{U$xP#BeYiVg00uM z{L66R0d0#|7??nduf$3Q#O{iZG3k{Y`+jl4kSU7_0COGcCT45x=Wk*3Z({xFa#ga!K z{0)%(Q$fjhlsSBm!z(`*_pM$+4C%WS20 z%Il^Id%`O?2=%nG!6Tb^0Wj}QLVIe3rFT8}M9TbpCX3^FP4wqieSC$%XS}*(A_@Sj zwp%_FdB-{TaAZ^!-(Ja|46xCy9EN-mE{N~`?cb#rNg3Mxiw_n7D+4Xr^Qn4auNPJY zf}ysOWX5n_{OhCryAu$n)iGsAm@tKNGlY~ne-Y~iAl63g6X<%lY-@E~?+j-yi#zn(9 z!-yKTuZz$=@Qj&!y#syV*uMkD*jVN>U+ipcXdzR7bAnCYKRi6;^G&smLlna2qoq zeIOw~vKIQI;NGnD%wr+ijV}!zY+LXA1+Q*z@$VX6Mi6tYphgzqN)(w+5`=4>trthj zH@t%#x&N3G^nqGLb7HpZJ`@ERpEnkooo8ybDQ1n)7!7p$U1JbfZtdJ9X1oE zG#HsUvJ>um@}0kXs)?m!{-&p%Ife{W93P?epYW*tn-WeyypqyjxHw-)vQ}_ac-r3| zGY+pdbITW!`75J0G_Nqe?5@EH?a|D=Kn=^WF!z8 z-RS#{zer-Er?RqA=43oCT3iW`y{dK)LODbv#VN5tI*(JrW^*bN*m^AzFcHc(gQr(y zdivv&Gf)8HuSwe(@i@{+Np7u3IkO32u4}h3X<$g_mA4i(n%lD+u=yd$W}rF@Pv(&x(}FugG2GYz9;Cy#DC=2QIJ?|)c;N3#jI*2OUBy+!$!ct6=KUqRqb zPGQ#xl8jhKO!!+w)+?7My`&Oe)DdpoWCGi*OMf^h-|pu7+rQ$ka_?I|P;{zvo31qI zq7@$+{FqG}L|Jn&zCkp<6Y1PMn&noVw>_tmcFOXgXVtTx&PetLKF})?a4Y(UvrDak zp}CZ)RjNzW)@6AYCJ8o5vKiqFm-`^5JRlTwdGPyitv53CeOELPq+?;xUH<9QhKN42 zVSA)`TrrhS%lbn||$!+y(2qN@{-0YbZhfWMQPsLMAAmN~T@Id(EkgL{FK5&ebrIr>G z_mn^MIu}?Iw@s{*Dr;a`797p(n%||GVus{5F_ch)aJ?M zLAw?hHa)J}V-x(208wAqKdr$da$3*%0;NvdG-N7nt8pJP85lAaYQ(R+C3?^ghgydI z`^COVy|~YimYK14?YJ`dGoRtwn2Od0ngBP@vfnH((}W64!Z`3|!=E9tHjmJb#y2z^ z{+!jlvoB}O+}gLnJw+@j-prOr8d@7#vj)yidh^L=2yYOGewF@rI2?L%v@klD$a>>% z$V(fUR!zRnm(%pmoR06&ooQl}(MXESmu``sd3`dr5FhR8h=T;6H+x3Di*E5LFrzS`T!*q1AW)a*@uiB?@lCGnrD&fzN3 z>pv;qD6MORBb(-0|tJito8qWQZR=?eSe=l+RA|UYf^f-?l6-Gl@wpIeO zu(e~cf!U9d|9jH6S!XKoVD`l9v;BCo)8I^vS*Qf=Nz|v)rHD38r8;WqNcjwhU>6p6 zJ{mWfI8F_))GYbs&;#}f5B|lmTrsvUd*T3imUi|NYn!{*y*=@Jil$X9NO*Mi|Ex7&qN%VD^88#8NV8p~NZ$PZ0!ry_* z-FN%3yg*l+Z!@leZNKNABc#Gy30C%=KSZXUK$aS+|3jah0WAm1^j5+3_nxH~(=fbv zG7Rk1U{tD`9O!nv&h_?aNM6o>1ZD;7(5ba7lBS;duZCRp2dIYrt+VcPJ6h?!$uJp8 z^|?Q=Wq_Tj33@kKqGr(6q^?}8YM^dIr}ieI-k$7oHcTowlADM*zSVriwL|jSLq2u~L@J{vo%$$khv9{2kE5DLtb^s&RNN9}57snA8#@)D)gN-T zd_{qQ@A|d$ECxUZ^Yf zDt{`4QsOH!ZBK2n7A2X_@&!ZnpanN|F9i0*1!&3`uFtBFS&MyZDl-fo%noK=S(D6< z^BF^W)`YT-U<`TCQ_YR-&SBKeYpL2;E;SacnrVcO;QScjx>}Xr9${IgkcBk$w(UH| z&EO*sK{-DWwXo4~>QTGDIqdn4ap1rG>8dhlc#++?Y`gn3BafUWkQk5pp*@CvQ_o1O zF8PeFtMM7>u2c77^FbGnjFmHS8HHGJcs$yigT{>geCM)QIjWl=Nmrn z&YO~lRvqmn-@Vk@@QwOZ8w`iC<7`U>m~ZrpP?jlFL?!Hc)U~pDG?o0Hlp7|KD>vJ7 z)pvuE6WuChed*UnIv5PIZr|b Xl1+!zKZxiM8xvF literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..fe9795acd6d0fcf7381beb1bf6f33b3cd88eda4b GIT binary patch literal 1582 zcmV+}2GRM6P)ncAqrN(W+jq#EtG&5t29v(tb*7@ z3pa&CkW_IieVw3SniP`2vYSRQK_n0`HhvPrirASLqx<~*XXjkcn>+XGy}R%hbKvZp zIp=@QnYnN7+%vOtb6sc@Y0L-RsuZ%tc1dkL#Yn-UgtSm4gDC*C$YJQT#ru?W12e>Y zyXgN7e-ZR3PdmUhQ?5s}^~a~+jpjXBOC+T_-^v@{Y4`+OjK|AkL2?G^BE2>SRtJM3 z?@SHo?xZ?_KZC;)rri#UuEBRClpMT50O%{YJPZ%q6j`a$z}r$qrhi_J&|=2+p9;W! z_(S+8yj>RBQpUnVM(A(^E~{fkFPknK4d8;n&?Wfc0&IdTCi^zkw|NlWKgipN@`NIZ zq@mgCQS{g7Kjd{mHV1ViNBTUr!;(V;?gntzoU)*t5~mkpw{TF5!0UkldJD8GkPIO#nQ6-9$^^s_%Q`Wvtc zitdEtJFwAyMTnhC-J`YiAiOCh6 zRVeDT?Kiiy-*Rx;X; z)v?6Aw#5Be!6St#wbukb7)hSAOlrNYcbWLM8b9hi`2B!evn zr0H@Cl|wpEa0lUgZf5$ZlrL*j$3FTb+6Ajx*Ih~zg+eZZzNyO(Mz_+JUBJJPpQ`hj z*hXL-o`!IaR4%DhQpsdxlXN*6qO2{Wu)mu)eoDW;U6EkJB*7Z}#&eWCJz-(_cpA!% zLgn2)Sk>2Cu!EZDzeCrY3OMbo)8 z=l+aSt_}u++pa&A7-OxvAU>BVCNKDA3H*E#e6o|b3#g0nHl#8{ zyWG_TtP8=;Teo~*yG*o@$81~^w?xwMbjc#d_6lv~*IPDt1x`uZua-|~2b3<_{1%NW z&`CvBs_C)qKI#mo0nauuQWb~k zE~gS+)vuPQibkWevppL(I!3IbR9m?wQ$_R6W$TE{=0W(AWLC4k+?pOS6Vi5n1U?B* gSH?Fb`#;+M1({qiA>QYkzyJUM07*qoM6N<$f8XP)O{i5>6vv;>&oC1wLLr1Y5W`UP^#LNhfjpZO6dEW=X~Tw2 zA`yuQOoANLKnxYrnO1_9RuqjCe9@qZ4$KCxn z^KMvouaE!wuf6yAy8GPQ(^I64j*jk0$AccVXw1LF?zK*%57&ZIXrKp8aHi4As{Vj- zJOnT29K{XGZ}s9#k^#d|Ql^%opBqY;qD}xC(4SR1(tpG1e_4wud(Gh~#9#4T_e=u+ z1_L;wq!OSlz1QVF7mF1mY~2s})+81klz`C}hLWZQoL}JkmV`wt@6UmF+(pveSTsAh z0QvxIjDej0JeBw5FeElyQX99I?eQE-ieZ^TcpJBsLfFhl!q+H|)d2_`wQLH&_d&?7 zY!Z7zKD@Tx+0QA_Br7fAX;*S?8SD~O zQLy1MyJfjpwh;NdLIaLnvbmWSESi?fX!f{S%_&$QgS*^clX3y?cL_(55&(gJ$>m&4 z&B-2+F3ENWFlH+Wx_nD|7tuDXiehXZTu&0@u{Xk5bI^kEZ^B-M%tC%Z4uPpXhloFg z?*)82=(}wKtN_Pk2-#BEP#}8(nQsZP*CAQ6{?a;3A38qi`YjQ*T-*z-ue1))Z-}-6 zJDGwdsW8V?xvi<#O`oWWE!|T@P5^1`o1Kh~0$Z~(RUMnsQ;sC&?sbe*_B~G{vFB8T zrp|p9&vEW~cj_V(`PeNT)llWw~g1qmIWf^iz56TxK1QU+A>JnSQCQ19`fQ%y@F8eZ#GB`WFmCK<;6epSx@f zWK0Ek+JP60dDAqPcOwlA$|V#!`^Xt_c@KvQ`Nt@Safy%ToSp$@hTw2FUoM+V&g+us zwd>d~dbnrsUGQ*Xp0c>84)7mM77+SpYDfAD4)?dlqvSRKSeD`=>vKd)@NYvtLAE1n z0+{#lKkECtc6S9Hm=)jxkk^`b5pAL`s$u~e-sn;bFc|qNds0V7e;e7>ApaUM`y3Me zj|TY8h8Vov1ekfX`73i^nw1?8*0|tyL;=zM45)%+2rU2f0XLP7$#2*R&fh5k(>Oy6>PD)+>f9y1vAFqDL-6( zRcaU>>? zrCi9T`Jcf^2zY8 za=7yzHfH`wKwj(0-&gcKaz^WXvW?d!uNtTOHM@3q1t!1>{0|FL(}Bxtyp;d|002ov JPDHLkV1oP~bL{{C literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..4617f03ce4ed4ff7af968abaebe1a2fd86f7943e GIT binary patch literal 1535 zcmVU8ogR6vyv1%OJfb5t>CMBoP%x2ogqORFK(+NKvRz50$=U z7l#~*Fo5~X(vkv}<`E4!9%aS0@aXGZ9wN=*>kiIG5o(0W0STL&% zh$ra33Lf?2ZCsKQVUXDOB4JCyT+%1;IQR~n1JlDIV(BJ?xoF=BwI4^(>bio1Cgjg| z5VLr0>yvyxMw%825_=!wflg!{bccKa`ZGns-URW(S6QEAepcM_=~%u@*ls z>F3&Zgp$}>Eo#lqI~EI%uWR{rWMhC4Sx3eon81d0+G(7DXWMcmrQ>qGkO}# z10S$&_SHH=2KYz&2-|PM__rjH=AR7~uiT<{lM~(?in;hXi__P+^ON;Uw~)V-XpE@1 zZ?T$KEbBK)2Fbg&FxU(P|Mf-l>f6pFN8F_ru@`+I-$(R}6SkY+lYYLi&mi}?U9_+W ziQ0!;y_%PbaFQB|r#a%bQ@ zgheJyY`4WNR=GuRqZ8fYixIoc#ZUTi`NX?h#5%#Y%LnmyUG91}z;f4*-fF@Lwe=z2 z;{+CjNf-aqwMi4!lLLVcPpZC1ZA%TDWD#A2OwBCSVdLPU z7NH^?NQ=bAUdgK`zdfm%{4<(YAI%vznhb)}YJKrV8BQtzX-vd4P{5&lg*e#n1049 zpF%D2Uk($*Ry&cbCRuE{SwTS4-MpEhQ{5_}EBmQ59BP!pZWZH~>H*io<2%9(DY{d zxtgX?pA3__3;3@Yj?m9sO_5s<^ftguH|5*wn^6r)Oi0Vf5ny%-XLg=6d3{6hZD&?J zMSAEt0G4Le^d!!J`+!-;SB(_j049t;yIm8bwGHr6jW>ES={!+J9|Afz%pS?BSB}EP zR-Du7sj=#(yq2ltJ?N!{Jiwi%^Klv&7`W5(qb{7!NbK;ET80mU^qT|z2zBYpX4SHR z3&1nrQ?N|2+701B@Cz_|zQ`aHUjps!kZ-?ldZ}}=MI?wvT_`UmO{E0Hq1t57T;wGT4K6Cw=vOfH9 zW1MudDjBA8VOh=6^$em%F0&)01tJ8*=7J}H4#CjI39O0G>IosP%mgw*E6(4P)22J=8I7Ylz}G-m_* zQj6OtbldPXGJVAMO0k4#b^chUV8H|$PkCehm_;k~H3Pwo2;J?8eTDxKI1Ka;1ZRQ% z=Vmcj1@w7SFUxnr)go2vz`bAvxB`SWO5hXlHrT@|qCsosuk&Dcy*wgR=qpY^)2y l7`U;jUZ3CJ12yk~{{fbHzIknRh`#^;002ovPDHLkV1muh=x_i4 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..dd63791237c6d753220903ef04cc6cff41742827 GIT binary patch literal 1804 zcmV+n2lM!eP)U5Hgx6vrnW%dvb&Bh(_PP#8bx!H4jvsU$O}hloJ2s5dF< zp$`grkRU?HA=1e3B??L+AFPK8NsPjJQ0gHysi>JK?PE|WOfx@jzyH2_ompp}b7s!H zb7dfA!GG3X|Mju=K6jsU_T6{7y6Q@!(Rd#;EWXOam92nFkl>?z5Uh-jpw*rd zyj@*u(W?lUhQ2IvO$C|tBL;II7to$TnY+NdV0u;o!^_dkkv0@H1uQfN?Q6gnW*0Qh zjRmsv1lFL;HUj;*+7jiWKC&9dWeZ6Q z$H+7&^50~O%K|RCZm#8|n>d^u&>H?dwT5MLGo94T?h9R|Qwl=DazuZrVDu+Ia!W25 zVgcBlBNIbeIm#2XU-3?F)83Z(d{Rc1G%U{U^$-I26__mpJssQxUM$HE0oiy7$|NQa zN4*Tknp^=z=7_}b{%q|Lv&1`+oUU3QaGEqBcIkSp8p&u=Ca0TepRdZT&C|)wv?JM3 z7S%4422x;yRf+mSVwagmAZMhtWak#E2m%LHf#yuD04GyiJ2Z)Tz;oEwfxnfHly-kSEI4caVsMym3sgv2CmW{^NNcDM}Kq{M`1m;pkuA_ zs}r4Dte)%qA#vEx)rF<_J*Bh{>qLR(R}b8c-(?%_W-?BuLSx6r!U)&f_K1r zi$mLr``&TQCV>Y)?z50Bv0$2i1)}7S#Yp20n;g$&ZJcXj{xT!6?OI1yrnb8nk*my> zwkXf#+A-j4j%+4gif=O*0(uNpKGX2^0!g+%OzUYR8$-xA4wzzocDW0k7(rmz=%e>K z?hb5i3U3gH)-zEL(|s;x1-8i&<44s*hdbM{TGWe2EuK0lu6_2?;586-qi8LdH^766 zM^6Kf0X@D}r!^++$ty6CS0J~w=;T0H>^hRwg0DUV$ako1=m7iOaQc^b)weo6Atus8 z_ZnRG#;ZS^5IKiQ{oZ2E#S3RbF94IDt9l~fB@2pLTkD&v;wOw}Q2X6L3%{A*)7#}Y z7xO3WrJWjZTT6}sbTfdJKyRHJ!3FRgI1F}xD}Y2BYuyvq11%%@9|rbG=(YMB=mm>_ zzEb=E4uM@4^|XRXEC%Cw<&xf(s83zE&IrYH_+%Ru8<7r`R-`?^Y4f5(DQ#f3g0P9P zIBYF99a3pSBiRSC!zvf24UYQoqA}Fl>{y{xQ^2-&R=99aq&c0o>3G08kGj1d1xdCu zNY&95*E*jNQQvV4s36sw?6MJ(vNk4~%Dz@q#E)x@)5)0m#4NMHM4kU-scc}zkr2L! z#l+3Vry9Qw)w3_jv3|3a(>^MM}4&jT+fF)Hs1e14}=|Gbh!tyRA}s7xkqD$qmX^&|(gATOs^hKOgu z6ChnqxlsK6A|J^9?zvpYoi@}buw!P8MPstVzt*}V@p3Q-ylleA z9ki!a@#hZSOZ>Bm(P3`oZeM)>_2p#{W7KcJl?DAEDAI@hA?Wcu?O%bu5=gW)nj2ap zfAnj$j!=IDbAV#f8cS*TW36vwYxrkSSXkYQ#;pbu$SQZ%5UQ3PT_(O`oQWkHle zR6Z0oJV=m|fe)b+Y9tC#LKYNR`Cu;%iWLQxsHLe{X=>(l`~A>;3dL z+y(!;rvF-dpYhvgYfDRqq!m#E)Iix1`Q7ygIa*UKy}BX6uAu1B2Q2ec{B7RvfK97p zmPrfj;ozX}XVbr$U~iHeeX`hwxdhBM26j6R+NvsR+P?)P{j3Q4s9?TyItMZRg^*AF zIItrYzeSw1NP$3P_&dCBHu2BR{s(BLqcfP1 z%;|(6`6|QUL@Jnz)m%%UQxf(eWzlt`Dfpf5gr9Vl&dG?BN20ru7BJhi;@&<@0WR2a z)wo0-#gXqVmbs|4Ts!~LX^^_bM6Ggh-By{q{6YL{6+~WOI{8zdG)SjOw|8sY+F$(X z-Zz{0BWC}{HHSJ5tURfQ$pE8($>Pd`QE`z~Mf8)t5qZ7dC5ynw#ASK$;$wk4 zHbw}!?aE=>{kp=q#I6XOXDk-gkiHGX^u1_A;?qLT9_S;;XtV2J_uFY${gq1>M{r7y1{LWna+GMTFU2JO1i|AsTb zH6MIR=4p3V*rLuWn+^8CzmluuUi8Q>VaWWr_7OZ12+o&*j6lc!>X zlDs$!lDtImGmG9>O&WvzgLTj8x`H{}*`T3b)1;Zbz*Goa?! z840m{+#KmIZ0u%u8sgAQWzG2}#B{Bye9LZ%^r(dx;CanP;z_vMl3;7=I*SMYRr95Z z+0yGKACKCQe^(Qq#4WrY9&NXS3rIuKXrTfz9ey3K3U>x zpCP%v40IUY=@IU6INA+plQ65bZINON?%jd^P!Ws#?7-P$oaBhik%n+1Y62JrO!i}} zWroWw&`8tgBRCU4ck0@1c@h_fSu|309{{mIY0@h+nw-fK)GhrhxHOXp4sq>ftpihH z`B)6Den!&wU5wKe>pBBnXP}v9fG1ANpV7_i*=fBvkX1mURp_Wrn@BST<^WdeNStWH zU2FPNBMhduzc#YQgUi8?6CIh_WgsSc=?_2AzNK|E*1r|4j*S|L?Iw0>X~U3&=Qnne z10c54_0-N%Y++udeLaU}{lM350Ga!Mz5vF8K|sI#w}DSUUhb^#T8ltj=*XE{jQ9$d zJAgf?s88iMO|(y%>|TZD8__)*HGp$};G3G4uOTttl4!jIMn*VqJC07`fIO#NJ`LV? z4Kq9ZjT%vRy{nZu#%iz^<#M{!{w#o}?#G!5ZUF7yprL3NFqvf&s-h{81`>k z*0Oz?26{dFvz>0N=R3hmKCaP{7eVX`#ouy!;1upglUo2x^x{ZA#`9yFUpJs7yr$7l z_~*HpzSGtK?Q7@_q-R8Lw7$S(8lOUMnBz75R^#97Vmq;41M7hfP+JpzdqO)!Q#zS2!1*-L z7kTfpM!B56x_5(Z+$Pe65>Cif5YqoV;mGQ<2W)NB$JMl%H17|VfRiCV(o~z486mc{ zor7(M@1MU+zw`=0(u01T%WD5uyVk3~W^f2p74_8y+Bl%M;zZzO5@$T!cV=wu9QE>q zU|XLn@n-^Q6J5Qj^wIq4g{Jp`%|MGoZ7()e=s6L50p0{>ooI7vX96#CEA^t{67Ul6 zzb(E|75h_2_W)girV0JD{PB|RRi(F_9}VUV{8xMoTMzeEumfm6Jtq1U*Efuit`4xb zaBGY}H%*x1&or~|u)FBLylKrls}ToPxD4y8IdzTuzdHke0}Vwb(;`g79RL6T07*qo IM6N<$g1)J0+5i9m literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1af3018ead573e0730f08a0fcd6555b2a7d64e GIT binary patch literal 1549 zcmV+o2J-odP)BQZEjSQN2_aK14wn^jHy5 z2tmCR5k_Pb6$Rl-7ZFVAA%ifH@GsWrm-)F7uI{SR*oW19q(Gh0B z|E&93-}mj?xA*DkDMN!bnk3dV9^Xfxw;=%IaSg_3AYiKNsmKZL?2yyvAutE5&P$P&9Ov>(x2gi@V-c@4zV?)sIiWH>^Hw@2$UP}dc-^Qpe0@s(SOyDkX z2wV&%fR{jWUU@+e5I0&NC$bJhnsB}X*18utUv{^N7gtZ0-wiP!B^Q%+*_ogrsf#Z3 z%i!Bn$#pgY_kw;f5wu7(S*K*Kf{mU_1{~W) zruL-IuLU0%@+>KOhZTOYT@m7bv{;>R)yNXJDGT`t(^G7w#k?zLwJx>d%3EPYBsUbv zjAn<;Gkr#-W?sbjJuw;EiSBnhy6#5}gK>Xl?hWA6l?*@0ZIz3q5-4_o6@1nj^mzmL zlvK`;Y!q7^3cI*|NX1$uS>;V0gT6^N*Sp58(QYq@zI#|2sR4x-fE|YU-gJ}?>k1s+ zVYX?*aXEpIx!_E&6Kv-xz8Bs(QCwS_J)jkB=%^Ew^?Y{PjIbC?0li=vSPFgvPNi3; zZeX5WXG|!>&9>O)`?5q{W+L$%OTJYG%ovNJ>ByZGc zp{Hx?@a()I_CMqcy40pK^0+!qf;UofejGdq+sAT1&&viMpJ{`GuX{`>PLdjZ11>El zV0#0Iwzv;@zYMN-%&GN&3PL-)81g5XWpMCew{^rRHp>d`_d@6!%=UrXI_6d|UmoyXt0l{7u zpHfOSBGH$q&t~Bb-JYsl-KJ#|#mt(e-WL5ux$KOxjU&a+RRQOS`G&GsxTse>8S3)8 zeln=K6c z%Kt<3bzP=Ge2sY~Ho*73Mqs2zeN!SP9_f8C5Z^+p;q27tZzp$hN6EH#bnOTFPhp`o z`xSmyo5sfn|5)MrX7Seo7n=`cv*S{yDsBf6w@9d+gb%d_^d*4*5a`d^%izm|O?$10p?t z=CRZMI@3n#4}&kBZgwCV*yfQshkRTNd0AoD>(RB{nPgmgq$9Vh&PQ2NV3fM`Mp}|e zB|vw-NRv}>L$!6X^(prJ2Sc_UGRL%HK*Fwg<&8{Y*#|&;_UQkt<={@^@&7Hw4UEj0 zgi$d_ZF96Ai?0Z%Ims^nxR5p~j;_G5x&r?LHRa=5=A4UX00000NkvXXu0mjfdPd`F literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce59ea71b1162b986629dd7b0037d9bdcd910c6 GIT binary patch literal 1443 zcmV;U1zh@xP)MR21IBGF)0F+`0Z2oXi2 zA_#&AncyZa6xR~axNxH+5{NGl@ev>6BBBdT&?KU6q9_tHiFu9R->K7_uI|2FeILW1 z_rSTQ>OcQEr*3uK>h8KDBW+{~G5)F6a8~}Dkl_ZH73d@H@{T-H4AOrzclOpG)#f<; zND1gz1NJ6GNIDXy(Rp$-Q`cL`(4VXRsDWm2-a~uoDTpwU%?EVQ+64>eLl5{M!}BYP z^V~rARTg<&9}wS=MZUA3+yaiv(?JgBVGVr$CBH`9j^-(9%L={j?jKOIk^!n zi}hn0{CltqOkL@ND?1Qul*9Qy?pJ)u`yh#E@*XSpo>t1-_6>=^c8^z_i* z7Hm61($mnA_$(#o)YKnfR@hUk+b+Rbo&i4Ld`D^D=KX4eeQTW9m+wJ=sHr>}le+0A zT-R>W4rBiJGr&^54E+K96fLaazDy2D7opiki}kXqF9no@tlzuL&j)Ot!wR>N)`dy5 z&Lx|yN`U{j!1Y96TQ@(+qN+R{F@mnk zLV00`iQtz9-#^&f(ZlM;yrjMYB~@hLJ2PkTV^wuU%kq zNV*gJxtNnuu*6XkWFM-xpS@@-uNhDZP6bHtrX_LqGmCeaZ$4%IDqEU5B6mX6LeMhZ z9)eb2wff!-{ngmr=r`yY=rYt~71O%aI+d0ppM)WP;R#^cYJLhn84ac&U@M)!^O84W zAw$bf$gw{Ti+6@S5H1!uCbsN9*2t&Et}v=@&HBb7L&9(dhBGjnf#M9X-&}=mMNic1 zJv+cJDn`wq9)p{Mu19qO7Rx~Z9sWO#?n7glm=RxvQR($5dx(lgsH?IWJ-=?C_|~BM zqF&ynlYUlGm%J@bQJv?;@;ktTXzinFRUPd5mH)>UW|YZIcoIg8MdoSyHWb9UCx% zP@G;@Y#V)r_n;fi-@^JA?8-BV7P-2o@`avoGpm1d=5&*dIGrP!*dGJkr0Ok(5$v~7 zV4v+K8*%Hs3FNw0gML+qbnOdigM=dSywP<09*YOSS zbRU{;q+lnpy&gP8DeJr3*K`)Bo2~xeHL$kJa&N8%V*Mc%FvL$8orPI^8AclMm xz6;UWb({gNSwWJi5uRzj zz6@GGHU|S^dnN-5ki`hZQb5eWz_fq~E@H8O8Nmig>dp7cWME+4?CIhdlEM0R#>wmu zM}cF;dW?achT{5CUlsCJaKwp-7pMqc>HgoOE~uiVWnsBE1E;la`H188u8nW)E+ zojGQ+V;%RHZD8SPvhH+QG=1AX)}-Kro*$%Lo(i?iEImEpiS)s%8mm42EB;-!OWE_1 zS<&GeyAQH2Sh~++($3x(sozXDHE)T1kjR)>FiAAlDCG`EyLLkR1Wr}w-JRY~ry4%E z-c!fD#?0)N+y=q@fvMaff1d8HV$td8n|j0larvAZhgE;ETTe`Q7OkcOo(#{+ znOj+p-s4$hU3uc6w)oYGr(61LUCUk6e;G;LoVnCt-S49bRt27IjdSK+?hE-WY&iMG zyQZlRZ#doxUbt@dns-MQK9>m;vUI-CXT+5Lp>)#a!j8Rt|Cm!}ukYV{F-0aR)gKd0#2-@;&;e?H)VZfo=ijkUzFnHg*XvF8o2oP(t9i;u@2tL|K6PqL z%sHJJ3zhU)U7kV*-2C?K-&(7$+BhXqd|T?|lzTY>w$n@%r+=Pdpx*c-=!LuQ{BP_x z&K)g?zBxzhbGc!KqvZ+zWo6ImL$^5`Ef+l%7w{rddhWAV)BmX{t29oVR6fZw{pt~u zU7sV2z6Jd}w(!}WlNS5mg#4CBeHF5FR$E;!kJrxF>8mUEZkrqYI5hNYu|d9~BB$cU z*^jkU@)NR?*IX!^dfis}eD9--@}&N+9ah&i&Q`q4a*sjx+~cmvcjiTX(dYZEv~|;@ zr4wFXzNvNBYtl#FQ|?#1>VJhyH|xB4VsEd?eD_Ho@1A;Yz3c0;b$Q=h7fqhh8)N@1 za>0YQrz*q^F2$#;?37nCR=1qYYv(tq=dSsi4E@=b|6RPDTu;t)`M7nWPm(;7o7%sn zw^SsyCHHe0P1^r8ugUb(bHQI?a-8$0>ITU6Pk7C9>c6SmJSo?xYZCAIqh!x5+kHPJ zBIbY0Bw3Dq#oIJ)wZ)gHr>;ApFhk~J?_>Mv3Kfm~&u5?Enc7qQe2V{qQ+|uyu_Rrc>X2p*y o?>gKjf2@sX!~z@t?`EoJ6l}97ofUHGAt)Pry85}Sb4q9e02E;4K>z>% literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..65bddf0190a9e41d14641d67ce903e2142284348 GIT binary patch literal 1357 zcmV-T1+w~yP)&#P5c6vwqBO$U+@5=9y%(GR3SMx~*G5Dg5<8a1;T6hbCq z10Cof`Ug@8qtJl^%V*@IM!gzj4RjC+ZAnz5AYXeU}$^ z!T0U8*ZQut_CEXk*yr3gV@8RzTCKmpX3*-%_k67@p6Wh>y8<4K>tZ_rUW@HokXI{4W59pPckMc?_C^TT68cx( zW`n#H2$FJZsHr97)5fzhN%!QE!I=lHI_}{dFKH*pUwvDWgpAP@tDc}KKIGXh z;LVi3pRKqU#CJuu3F+Pu+vHE#v3;E4rY?$GY!Rpb=n}sX`BL^P5vSdql`_UQ?*4OP zoBBC>ikq5Iir3gS(n6;-d=_*5U-*wmT71Q?B2_i<1d&$ne1w?@OQk&jtJzW%FNW@)ItTE+P zco&MvQ5xc2R4j6LNELVE2kmcR$I$h5qY&pA)4SGqT_hIXmb9RX8C^>sX>va2WPS}9_ z3AJ*?=j_QU7)xf9iyg>5E;P{LvgDB;x)ofIXMvSXc7!?m^`!$#pc-R!}9N|ulFo8S4A%6)sXg?=*+0=|WQHA0=5`#a3?JaOmBBaX%=XS6a z{03q@L!pgPb=_m1YFdCC%fYEA_pYXSv+)$thqa$f!K>&`WCLnC$hidA zRXb1r)|%UepfUs%ch^huNCJDwZgn*McF-3yUDBPu^X#sess z(ETRpxY2{k;nR_n=o`+zApG7GNJhaw2>+xBU1ap6S~4LUnEMj49@1r?8-;Q%0J7y| zP<}2?#jfJRkP{@)*2ar;*>W-{KbNOs@B6}EiAWeY*AH_V-G}Q8(3hj7*s`x*gYpw4 zv!rejg})HVw+p&LDCO>y(Sqj;=eN(CChRS>^xT3e~zPa7WX{{}5OORswAt z_4)H4c#jMIB5hwG&&`lt2J3+S2}C~@e*q?eb|tyz9`2e#(Puy%(bqJ61k;Z+3ml}& z7Jq5OR3vNrO{3^GODUb2&w=NGj@l1k5*)Fs0Z%V_+reX?MD%T8J2^h{WO8WL9tW$y z5}+}D1Sa5xf9|56l%feGBMXcSPCrI00(Uw3&$K5QSp6UWT%vI^U5~(jT_j#5kfLcR P00000NkvXXu0mjfzPOt8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..b8f13f341f82a24d01d379ba299d93290251b754 GIT binary patch literal 2193 zcmV;C2yXX@P)O^B6c6vvy=Mr~5FouHIZ(juajR3uRgv29u{EEhp)A1)$S zDc&fBT13#oP-rqlO5C)mK$xtJ3B^>>2TeGY873rI7Lhr(-~YMiJf8Qt@11+6xrIUp z&U?Q8=bY#LxX=5%&&(y4^h(WUvjI0Ncy}N_g%7}gWPpN!=6PU1iUQ_%8o3xA85kJY zGeb_4fdF_3*BA0%s)I-X#C*gke7%+`TR@QmP*+9U{aF(H1wJegv@Qq!6-6yN70%C`1Hg{J zXJso9N{@oaE0W-j1Zg(YZIEt>8_a)8nV?JSpxX?Tge4A{Pxr4yI95xuz;CX*#J?MU zQ+6gC3uGYQF^QV!PmU|h_miZ^FNFV&=K*@S6-vjM9DgzUbnvGR4Z!Iqjm%e0AZ(}S z$|MDjy3!awxwf@KBK;QzO3`j%O4b|0R&oR>@qrREXUa0qDnN2RewJ8X*(bVxLQT zJ=Bk*?fxtY&WHf?eTDs&>_AJEjJ;YuFNCVI&$j!sB(^*Pqz4)o5Idcb>FI3{FjtxX zJ^7^960t8slGL^E8YxC6kbddzaVJt!_#9YIo@hdc+9q-mdk7vA$Vf|o%VPqz-}E>w zD)$k~aj`Gvb=Aq*gMX_hX#{zzb$7&_OM*~=D{?JeY_S_=AD;6TAx9!&v z6XRJ2piAZS2a3KH5}_aPfJuGxIo%p?+ueyg=l(WnpsfMy6R2D}m0&SF40_x817YqY z{O!CyHt@x2^xbTWxz})BW`QmEDzi1VR=iijzZ*tk2){4XUl0DOYQy^2y=MCiEz@7$ zI-`RYcafK-=D5l0v`GWxwYk|Vkn>@!-%ENyMa-Gj`@v4%0p6tU(p8pF0OxW!en#Ht zNhaUM|3vWl_kg=9c3q?NG3#ig-m)i=U&21eeT2T!&cyFsIUSWYDMps~o=o(s%yzNL z{IVOSk9$y3K9TvBx2)E&?u(2?u#9CJKw6nP z5cx(o)7nmJJf}@vi}eDa+Ip{O(qHS^Xz{14mr~s^6x8L6w6}ZKG!WM5#c7oIKlQ@8 z0^HIU!vl12-davTKZL#EL`qe$3;WB80cs~|9jvJ$l20M>MP0VA%IWXa@=qU92BJHm z4{4utQ4@W}ahd8O8!cBlHq58VI4c5HHDdIlw*EnY2YG!Z70-< zw2sPwm0OZ}s8@eZkV4u&(M$a+xQ_JF)<;fdH?J71Ui$G9LAtL1BQ)u%1*>LU5MXA~ zSTv^Y3xrsmgt!#)YFgH$UHFJCbue1G)-9F1j!R+MmQOYHR)fn+Do;kX?~0en(Iz2o zrA>rFQh$ISgtf5LqHzQ+=|>#e$E!SY<~vb>u~kF0R8zIpBho}L>KCQ)1WKLcIFRSD zHH)cXr^i8Gm#@G}VlC`gr%}YTb)lTPFH_v9mwKwV#^AIy*6B$nbGc_D(+7+vVwWE> z0ookL$SZdA+7l869)~+o+LaAG-w(js-QTk$`Pxw6XqiatP>5@bMemc7!6#LJF8eU} zq^Ccj1)p-1s~S#+YWj_P5P3}*?`o4YBNRw~=ZZDD$)qG}RV_wi}MXlg(g?9T67xIjl97V`o(X_jvGFc-J$Ef z81fs}8O0UwZtR8bL*4*uTWbqEn@tGO9q=dE6_U?lTEESPm7`qMa9T)@SJlfM$Zvvv zUC=A)WG8fAKx%1{CINhB;0G;sE@0-MKLh^?b|-vwh*ea@gb@~2j&hy6=2{$Qz=L@1>w>r>hLVG)%SVT43q8Y3y2vQn8K0x1b$5W+rKX;0G(8XHGyYOJuV zNu7TGnR71duCvcQ=iV7-3R>`Iuf6tvt-bcSd!Mt;xm8vFaj8BW`FC}79Yfs7;0$m) zI1U^DZD3E-ep+2!{R{fPLr8iocnE9(2SJu}Lf8QA0OJO16-<6Qcnjo78d^}~`zjdU zZwq0v8n7H30DUEY5@;D1o_8S?odG5|j|tX*+LVdfv2OyKK`ZD0M}RTlB%re~3)Fy+ ze2uZ5GxAMnuva#czZ&RDdC@jl17?9iS(CsS3a$c8;1KZAf#I^OIAx6!a30X%^YR{s zv&sr)$oNhM&A^Mc=QV~}xk{jEz$d>S+oH;&7JCxwZs5<3 zz06RVbYf}??zI!4e+N#;bWS7Syv_yGRndd0q`(;j#(*hcDi{X_mvmwf&UEk>u<}lp zUvQiVvu%_}zb;6QjBx6}OW@~-Z=0X!G=gavF&0{ zK%%z6HUX>$UOvH)cmQG>1?;U=cfTXka;eBpz&RimO|~#A5S&G^gK2LG`7yrHaHOgX z>02S_e9!g`t+HNUp0eI*xbaIbtcX_-x z(tFc<;$FccLpB^WxpWd^MDKdginTXT|g^(;mH;}>VYq+Y#^_%z);pA;5WG-^L=KF zt3oZWKj=%@>qwiwM4hgUaA-z>4ai zC7}C|(H;#JfUUsGIX=cy0pDaX4f#4Fe!&vgzei-SpF9|oF%m6G)e zL_JI1w+`sK`oR|@?E2PZrS!W9%ng=}etThc0fljW)Uw-6(+(QF5j`z=y@qOQS*a}qMF}}hv;_2BuAkQRyi*+U3;HS@ zVrfOWfrr%1;81LgTQWWheL1kV#bFt^CFi$f+Qm+Ls;Cma1*te;eHX>F``x*LO@HZM; zK9z}7vX)c(L(e5IhBClY74IsbIX3~ld!+tip%_IroLj)*5^a~DFk$6M6VaZ5Z-X=R z-nfqtd(y(BY_BwW!d_TCS3-~e3&GF?t9OPiB>6+{LZo{a7LZQq8DW9?5)k@|yqg4z z3aqSH12WD6CW4SG9*~48nUw5Tx)tc)A6rSRzVgYvg)||_ihm=R0a`!<+oyx}f2s5e Z`~x{G2VS-Gd+z`M002ovPDHLkV1k-t<8=T4 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin_mini.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..14051dfa719106a576fae284f2c7a1f9c7ebfe7e GIT binary patch literal 500 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zEa{HEjtmSN`?>!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bDfEmFCNxGL_n*mgu?&;zf;=%iN>TWM* zM}f9xH{OpmRqda~r{vW{J6 z))a1CCTN^#75Zz*iYtktRv#E#ll-Nxl^%SeG1LEAV`;?c$iz7*qYHFEQGD z`icB6^9*B8eAb%x%`~cA?(adP@Ldf4uKQH{&x?M&wjfI-**WrZiSh49gV>fSlkL>z zpP6;j(Eg=#^28T6YxiCJo{{oj=j0q6mS^RSTkkJjpy-};sg%jsaAA#Ymc*5V8`i)3 zIQNh1)s$J^jFwt!?GEbvX}RU#_p11(|CU%TlK#M|w(lXsv9%n<(_gNP^_LRNK4d)O zM~m!qhSJZu#^NjI$TsdmuG?dV;W7}a!p8#A z$JoY={aH~IJ3il7y=lk->mD{(dx6hB`41cTUb&D&kLOpG+e-xgq=Pq*Pw<&`Wgd1Z z6X@n5bI2Bc;abyH0ZWki1ZUsHJQULpT3rvF1Iw1EH`~~uS>Sy$f>#osC z0bMMNf_*MqYkv|v*{d(+3@^T)VFfl}KK1ifTqq7hTmd&CIGjA|g zA0y;BASYZsKKNMS^cwsCyI{=c=hU-6kDdkKys8%{d4ChR08!+fq+*ncfQZ2Yu-D1k zJ7B}e>9cX?V|aRfZDuoj3&6fo^Zm{BEAX?X*O%UH<0TYp(Akik1)z74pO;+NW`V1S zyC-i5kiQyT1z_=#x6Q&wiuhMWDa$nEdldko_llH=vTZt@x8&`Nej0oPFRd=gOhP@X zJAm?uHh&;{$)_NClcPlSUWcH3To(CYeNI6(Do3r$)g6!^*xrCG@Hi@HO6O1kDS7nD zb(1aBD`rxAE+A>U9m)RtJD^{Q*XompSSh|Be^b{f#6Kii=M{YrO4hW1P>j2@9a6xf zP=e4Fa{ebQ6s!$f=qII|U6#QS_zF^w&K63YG$7~89mpNX9k^#5xCC7{!0JQb6M+B# N002ovPDHLkV1i|3Lk<7{ delta 688 zcmV;h0#E(E1;+)DBYy&pNklFvVn;+wAS_ z-LAL~4sK@t|C#q@{_}S4RH8(Q5+xczvBGcO?q5u^5m^YRIwXvf z>|G*$1MoVb<1}4BKk(5bV|I3+M!a#Brvb-VnTLQazrFA#UwmPiOAS&^?-zyV9x#krWtO?|)c;vd=) zY`K8Gz$G0@uz+!xd%#;@99W+v`J@8Y1{`PH+G5g$dh8QBQ}Rg!tO+>I6tKD(WSSvh z$Rqy&=q(EQkO2QDWvBCf*8V>^9WOgyRJ_%1NGY0^v{lkANs~n;U!p{b5+(j~Ncsyz W+~aKa4W6_B0000!3H9qs_+0QmUKs7M+SzC{oH>NS%G|u)CkWs zUtb0-Ae)1Mu|1Q41;}CqVksbIU|?Fn1Q%gmzzk=DjAYpJ?XxhDlJ|6R4B?PXPDx0Z sz?@`|z&I&>K@OXnLNoJBW+4Rz2Ddy$WuC7LXF*y#UHx3vIVCg!0DGPtQ2+n{ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..91035e2a412021ff692b27dca058e6428d2d6a25 GIT binary patch literal 3186 zcmZWsc{CJi8&@>M*u{`6L$bzLsH=9KQ>I-?=0hH<(;Z2A>B zdbj@@bt6ZZhAYj{t|;kJ#es>Hir|)r$%xkd(Q9URnHOpK%&!N@A|{I_5bSRRc#C`w zmFyFkgA=FnCT_jN%g2Rj8fx7t_^`f9YYxC z;P;PPltB!61^j6wx(wiXk)IR+=`Z!Y;D`@#E(0VVn$jGJ22klfD)*@NR zn~`{soUz-LKBEZp*V9^}P?4)29dnNqcK1q(Y~^=uH!KLWP5ZKK@wSUrd}q_X`gpTD zbdixMC5S0mSVr=7&Ab$D z&lwa1mc2c+^+{Ckrp^&MXPFP(JRj>rUyI1C+dl7^ME5UD#(@^?iUP_xGlJ~d6+GcP zzn_1x&6&`-CT~6Fu99}Qjp;nw*Wvg!mYF?~7j2F$c)U69CNY#E)wjC3%28t^mkxgg z64Ytr>y$cSg(R~YJlJozYJi+txjBst(}l*H|pu!n^@sv5;oA*anHT_t*IDDkM{7x?I zKsLWDD)yMuY5sXy4M{ITLku z;%-~3)YWnqQ}O{0oZK1)0Ork?#S5p)3p(MM$mub$RldzA0N za!`&W^l2$(D-e$R-!h@#Zi~sGK@@(?s~oH=k@|@Vy*}QleV=!q6LrLSiVV{TDJbWv z@v;o*sgo4J<|^cix4Odcs6q}2T!MGs<_;44vg9`cQ9wpG8I?UVZIClsSsZt2zJrVX z%DBHTs_K$0!Cj~%uM#QnhR+$z!f*m^iivkxG=VNkD5Ax6!&lk5m-Qi-oyYACc;z(% zRzoD8=(%y0MiGe1(M$FVN)V>)LzxCKa8F&tVu*Z?DuO_ls0U%^?=bk|&U~*#eCr9NkiXB@Xw{d`X_it8~ z@3PLbDzm{CJ60B>pKBGE%YNlam>&zJ&D>$;EEPT~iwX=4T@O7AsQH)+8t@)FZ>)Vf z1=oZkATJT9RB8o{5&gn?Ec*Ix+-&69xu;{hc&uKuMYWy9&(U?RUl1^?3G`Y;Eba-G zIEh;=(c1$WB(6HSDDFkJidc^C2=mTN`G)VMwHVAO34Z^s+k{>Q<1l!uCIOk;zB{CT z@lyb)9#axDdl0iRV!M18l(uvL3etYylBxcB!JP`59<%=)KHyN;F?LQ zRfY=GbRt54RUV@D_`TQ6De`e@K)7~Y%bBc9jW(iEARulwpt=L7?cF^@EQg~GwSW5$&IPI##3fOqTs&dvt!|q^j%_?Z5Xbq z%yCF`U~vREWl;iAj3K_szJ7`R-r<<7BE@b{X$hyiqs{3Rw`vcWDyNoB4D6*S_?e3Pg&rgBs+wv zWFc&P`1_Y1k)bOT=x4nTjLqni+4CVk_c^%R5EZoTNV03j1WDgYpa%$vHH?N+oT>(& zxOfN+)229TG%5U7Ak{YlTN*c39a5}F&>HvZwBU!=xxfiTC5OxX=d$Wj5NI22Ho!EP zb;t)Jc9>D-7h~kyNvmVcjUS(tRjjohV-n|jgX*@q4vjuDip>{9)z!mpf07T-Dve*@ zbk(&`29hR*@quj4l;q;lWhVmL#Dw=)zVO&^;d@uxs_Nal`mbKzYPOxKU@Ro%4|Km@ zN1|FGJ*O(2Z>jW5Dv$nexwe&EF2bZ=HD)=ed&32w+{B{p6ZV9awI_cb*EK;5*NkMW%jj(g82HyBgh3`)V%P@(GUwL$uB z?li2XZretN`Y_NgECxSCmc?NW99R|MY6F7j4wRVbjy( zd|=c36pc2jH>vP(o>39~DEphU+DCr)SIfvcrBd34-@mquV7Fxf3QgOB+;>c(zc>xh!hod#N_y49TTjw%xpKax zQ1aX!owi5KC>J!@H-2*{jSD!;Sh*Sp<1b&BBYWfc_@S-8G! z9@RDE0jkU^L~~NPud=E%Koa-}Gn#OJwIkmgM1ZMuAK}n}@v#pB<8PTKX_x}wSX!`~L literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100644 index 0000000000000000000000000000000000000000..dda66dfd0dca9e7cdb6241e55cb59f80d0500f67 GIT binary patch literal 679 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fy(o=IEGX(zP-!LBO551%~Sx3}fGZOu(yw(;_w|EDYe-;uS}zGnMpq4$4>`UfTU z$)XJmED8*a91aX}sw+K8Yn&GKh&&2z_L_3+@J~|){`uE>QWbAooRU13y1-Z_S>1bv zL%37dGyVrb?Q%Yes>^qr*0%dR*MwQM<{|HQ%fnS^7uwZ!{A8#IS!}+#(#>hsMWMLO z6CYk#kg<+I@9K;La`Qf`US_yoanNv?(Bo%p0kailo=C1_-TO#HIb#-ggS&Ou=Q&p< z-P<&=vBDyaLC$V*y zIGZsfUD13kbH#zESF;&^ym_#+lp){JP1v|$!s423d=I$8GxFF33ftaaV^oP*zEtyo zWf1pnO|Z9_1mGb6V=6Fs=(1u81H%ZW0uPgcl^+tG*wjAY;ar(IbN>~UCo`t{hpxYL zhr=PiGXB>&@D`jC$`K5n(b1a$CduVvo0Gcn=aSn sFVdQ&MBb@0B8jHtpET3 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..53a539fef49e7e85679acf2db1419a72827353b9 GIT binary patch literal 1543 zcmV+i2Kf1jP)XsBIJ! zL0c6nq1GnRB2`NaA}IQY2v$_mNU%{_DVnA!2`E(XFYzz2wOSRSwJl1EL8--}h}bj; zt;AMistvilf z)@(#A3EbN^xsDwAl!TBXDpnopP8_KfpGd77zxJi9BS-YR{-qR@k%JP)8d=SRIQ&iW zX(D-(7q=w2qHSC1aqoNB$C~^C9XsVE*@pq4e1Qtq; zl|t_4x8vcMh<=~0&x|d(GV#~h z3I5?NYmx29#g2&F&Kb0d-x~LE??RV^lrhJ4C)%31Km^Xn5m58g=6GWpZot}YQo6ZfOt!>wzugZ?0D7}$A;?)dnq z^(OZ<^Ms~-PGdjn4cl!_^LB2hxCJ$gZSUA6>(w*7fT-=!VDi9zomKzV|Ez<7`85JQ&`*hc3vVdzALdOw>c zYub~gvSWfDhMslxw6ZC0D(ht-Ua1VB^1GA^f#;dsf9O&8=xCbWKA6VBD3F2RbFDF2 zzanqT@d%5tClFwXK}v;S5#sFU1h;G951Fue&valBfB^%^t?hZ4fwxZ+i;=>06_)n^ zDgbPCU;)!-U0I*L zuHdK2gkTCQxw(raydv>-P;I~jcGlnvK9!hCA#(cwtP{$;B7?98Ca`^$^XcmgbgEJa z>>XUgVo8@3VCQ^R>rbT+jUE}S7>_np0d`LOYW=Ac0+l7#u$9(j1=!!I@}p9Sy&fsl6R?$5 zZNLP!&pz>;S9PjVh#_Xestj1b z^w~hxr>`scsWKt56yD+^w#aT}2}KnZPY5u8<*Qb~2Ye|rr9x!u1Dzf_RF*chpqd}t zFcyWGf+|&~%31{2Rl~7lbi6$_r8=m?LO@_sy!DCkzbWT~vsUBmQ1S!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`=KafEmFCNuEw!tjoZ_Z13sf7*fIbcBXxY zu%pPa`*CLq#ni=?yB_dcza>yWsf^34Nyu@{8_|}>2b_*NncOuM`xd5Du_z`vQJu{t zSI1wwwWF%FqIJ@YHTSo_)7hM@P`*3=i{2jowwZ6z_J992{igkAr6eOJw*wp!jLHct zJq>~esGR?k9lq!{A1}0Nt?=D)Iivl8RHn1~-7R|^|4XbDcD*R@_X!6>+J$usYTa(H z_z^2-Y%Hi!prpHnKO^;Ma`eJPmfa>3Z1(0ajQ#5W==Jx7dn(K)On=XQ>95%7TUB%3 z%$wc2WTW*Y<=@#wUmSeDy?GQmC0Kg?y2nL7iyiX9zw$deED?C8yti2I=+>_b?^NHL zzC54ZNTygT_{6Ix2WQ1tgiYUhQ)UAD2WxpIHw}U96AR3Qtyb?}viH(tdE55XW(N9)u{QWE5R(MazBE59J>wjz0 z8Iy0`4=7#3#UxPC9`Abl_z?@?Je}`e&I{O&s^o7gGJdRVc9!{=|GVn}@0dai_VDzx zFumv8BXjB;i@kW&h3MnPL3XjyKJ}hzmtF7kmMvG`Yny7gH+N~5RZZJoycErm=r#-m`bgVx-*3I0Ya&7tZ5_S8ELy&N zsmZeKEB^%Wy39Hx`z1z6eX6QhsL48kstc!AhZ(XZuk;jkiIR^fxVdpt$;XPlLOf0h ziOT|(MqOCrY7pNme`ap^wdBg2rB;_1IGDCQTFah%d&=jT#Q}+BIoR8a6)t z|B1V3a|uJ2ZNmr6qo1U-y>(U?o9C#Y>@3D00Q!_3*=r94^JZKykg|v;_`7++BKTk>XIKz+t7hb5Pvj zaDV*f&Aj*V|GvN3%_f^s4Eh@c=G}c4UIrq38eLev;G4dtfw`ysax#{ zJ-3rllR-nPiNm|IzzK|Pc!X1*q%^z)8l&cL3r;MFQFW|TC>lm+JZHoFok!=5!%aeMM`7D>O>^l+ zbALa*ytjOs?H4|Tf7*LH>$sVPoUi^lW9ql`b98QN@s@IJz^LT}LloJQ+@O*H3jyJ46(yY8guMHLM}kXI8yg+DKoJ-cB{9f2-Rq zn_4muwH?Q$daPvH^Z!`6ox211P92-lbUqE7zfZuWeHJ81SnxME`gBwZ2|W8N7pBCf zuW#6(Q&u6G&pKa_?QP(o@&0|gEb^!cdfz=BqvVSTZ%}Tey?Mw zeou3cZF5HTIK`dj-ycio_LdM6Kf8x_@O~GWv0L8o$5d%H?2D3C4$ge*C2pP5LVBnw zJ9u9aV~=RNI(OJ>cZoE50Tx+oYAeHa=0nev=Vm1@KQv414joj zby|>`x^-Vjk9~&?{fh{#kaN?j4o4MAtzVv&+}k6w%hC3ExnjF74Rvp)FC=b~Hp;m` zTFO$Hh9X4YkrT+^libj;{kFr&DOn=9u0FYZd1a`!Ba=!dlQZXJsDndwO$L88uLm4A zq9|jIR>-bl6I5bYZSWWY#h4t0a+n1Mnwe(CU;rjEZF^Q$v{FdZB~=ZFZl4%Z>9`}x z+i^;O$LJxemWom17O>~L+Qr>ku&3ob$Dy!ozAecB+l_s`6d+312Qaa5l5|TY5LoB` zKGQuc#@e-~B#EOuS4>1deLksCpC~dmYGtd7^meD*29%PzcbQ@r|610R2_=-txhe0_ zNvynoxp8xp+^F|!B>n_I2vCLq;ESfWfLecz#|rJD+BUqAl41)Zb@-8n7&Tez&C%)3 zRI2K?w&GMYDmUU7O9CqND<^E=RWhZD?x|4 zc0z*-UQa^)=Yl_`w|CEs$- za9`Tl(ueSd0` zavSg^(XeRIZu5^|)h%!3kvR`^i7i}ddTUhTLJK@Yv0>3+-pa+<7e~nXv>elvv>(rU zz&+;?MQm5(z5w{of2d$tG0n&d#pS8ozWVB5=7fyo^tKdkY*0yg@&=vL=sKvx2$3vl z63`RKGITyu2!;nfSJB3T31C}m1E6d3Xb>^Ux9pljf^j=fS4TtY*fW335^)oFeJz~h zT86pUXD08Sy<);>egB(OhAnC~4(p=dds2RZ{pgH+h?b?g==Vu|ZrR3;{^Lh)Gv!GQ z#-%OC@17qDRlTsZGcdi_K6F`^b(g1Yvlc;9-qYlL18Kq2YUdH}63Pyy@^sS&p{k9; zI+CRCh!CF50sV8vx9-Ab3uCMD)1JlB(W$* zIG-J6AM5w`N}sBwv#!@QL2%P`cY17BLip`m%bVZ)Ssv}uaHf$wvKe;(I~#ak0Eo3Y zHR$*AV5n@@0Ll<+beeX!Q%zpI>~+5nHV_(~yzV5ZOQ<`aE8aw{UNi0|=+#W9nD8H4 zjN?F`f}?dyxIsa;4jIs+7<4 zXB}$bKK{WJnt`s#_r4S##sfNgSE~fEgqJbslEWy!tn1S?5*UKuN4}fT&T)H<``Qj_ zpSn4L`##z}rpMymYv%A1O+EYBp4Jm1y|dlXO`{aOxKD(I4oKYL0`dY~GR<-uDG;a9 zii$c&iwsKs5|sawtez9rYxn}P9mO&=bf8O4q9X?(1;Qpl{empg49OcRwyOe4K~u%Z zD@V6l-vu0wQtCq`4!BNzhc&r=se@6keOmsX^}Fyu65WMajh_$nq?5JkJ-apbn94ds zP*vuLue@1_2muRN<>T-9*U? z$o?B8hc3}_S9JjV4Q5Gl1Ey0LRi1}=taurqp!KHrL=mq}u62yviZyG08;`PQ*!1Le zd9{oF%jQZveo!tkA!gB^LDKZ9e`a`(5k;uyDz+y&?kgb&D(8&x_B88Zyk{zTwDC(U z;3VgtTqKkHG&9~B_aYVbhgSv%P>X;h8^sxkIMuI(gEI4C)VhFMftPMLGk0mM;uKV? zR|v!(yWN7fup}#ps+u?*-`hgBP%13IM6JE%#t>`6g9F|e)>yQf}X4!-G|AIE7bp3DhPHvj#pPgb8}tz_3w+z|hnpHzuYb|M-neOa?DjQYs_KZ3YU8vUnY~PIDI*Zvl3bFjTzj*@ zwOsT0Gr27lWi*99153U_7+wX>Z$0dIf|tjy5pen#ulL4GvCvfpP{(bZQ$6`;JX--7a3&{y)@=q}7b z$cc}AL%1i)Gr*leCA@lY2Aq^NQzfH!WJ@BkFps7M$xpGyZlo7>r^Fq>1MYD-XS+iq zzm)kzUcG&Z2my>^rtN1T>Yt*^Y8HA2GKn-@Z!T1+Fh>LvCh)yuVB!0RkU%F`>es&< zE^?G(n|5@)h%D)6veSFI=SI4>@dVTRyv4(lBGOK z3uytfGeo*4&I(C4l~)$CxDx~4c5CM2?HRq2te6Fw2V;a0k`2_w7E~Ttf5kd)1rF_p zEPrLr5D^+v5l2=ZO5L57ywSRb6~;{6JbXzPjWN?t`3yRnNwqZDLD$tqB&)f#{H zcyNH!Q0BTYnOQlMhh(i1-z(y$!e2g1DabT>3*jH)v=v&IPKufLN^QsZcUQJXvqEs1 zu(yen*W>s7cCxUI3hiM^l8&Vp7vD5naAlOK@ka~tME$|>Uo@5jO5SgzxhA>?VJbx) zLYX5DU3$-50;bruP=HQf$HIvqyL_NC_ST)QL0iMZb zJ~ynHGcIp8FOFND3%FARyE*u8lp1aQti5m?c=yKw#Vgb1g2@Wr*LOCl*-Mx$lwQE$ z`}9>@57K^bXqYtc(0b@1QEQBx7QHb%?@C^Y^6|I4c_^HrK1_hcxC%I?3FZ>j9(!3@ zMuP&G5iv?q%8?b?>nCT+eLjF8io>UzfsyJh6bI!(vfAY&&1#1=kmMwiD8EWwwfMl? zt;Lq-*RZZRKr?-~DE_m6%mGrGKIJxzovmR_O zIb0HyQ<=PFuMt&P*o^xi0KD%boi`EkIk-PxNfNw9Jamlbb3jpr z^b^;!qujyi@A`vTH_D}`;vy@6ATfU7lPvVY3%~oGciF8afDcZTgAi+4OK#NxOte`| z0ZSN7->Xsmlr`S7X_9H1E*y z1OT02kG80Dj=fkuGHy8qZ|c;*5;sT+gVD(ujh~x0b1G?O$r7$!j?#DwsANw4G>v95 z$GLEbZjari_;S!L8<2cE(V?4bX@auIsMv3DJ1mb#C~#@^*BO6DyK2q%>{K8nGjYEX zE+_%Ob~a>8P{PU~AIM|?+0rE)im{>6 zD(iQM=RVh*-&^@rwg&Lu!a@N$m|hNH6^=BsCYXHasIJF(^V#5=$D4 z`H>rFo0%EZ=5E1_fQrd*kt^5kYg8~wac(>C>vbg`i)DJ4H_J=Ym{5Ghd;=T|(UUYg z`O6a)CZyD@znFk8n$dq_ptbYafYAvO?xWI{Y(MIjC8?3e2SA!IxtE_0SQXTqo5O(kAtpFc>&5MIsAF<_@OlV)Ct-r!Tlv)qRqGYY zXd%G%f0oOtbZx||*~(AZ%<#7Ldb z1!E9~)%IHswbmMo1~WE|5o>j5Q$?>g<2O@sBG!t{BDPhE(11R8$NMh?D=;ReUfXVV zxD>~Y&IPvh+W|MJXmK+l2>smJzeZK_Frb3Valss@53v&BaK&|W?#}iQdDJn^z&n(= zxIAj(q8Ert%4b0xKMMvFSP%2bqcr0muGnb_2xG=35gL75-2>kXj$w2vqdiNs{@q#; zCW5LADO#;XY+wdA8!MB>?m3`--}9MKKsV+pt;nJxc`uHJceUE?98+|v9wuLsh4vX2 z)aD{3pMB6F+yM^x>fRUgbgEk@*N5vfZ5;4WnlV%sq(JcW7P%oYC*S6-i;LRAp>kDb zqCKVtp7qWKWo)PW#R2n7t$;CXNSR_y(DGuR2lt)%VphzWTW;eC)%-@IK$TMB`pfq1 z&A2xS%okLgwVLS6cXpyeF$Y}X3O}^`^mQ|S1nRe#PT618@s@MsIz<)*kdnOk<*`NJ zAs)4{)*ZK%5IF};yy$^Kxsv;JmDV)TFQ!~a2XHZMnymX#kwCv09PGM{3-!>U>HxDC zpA6Zi{nvkP%8l38O5x`K+RUbvoytEJT`Q>E@nV_aDBugSSC}giyHl!#X^rsT4m#Jd zo}yvQynPh0Dq&~rxu(}VTyyGn1wKY{WuEHz)^8F&ZO&)8`z-->KDFlk+^msk6!hf& z-$_b&FWlnn-=P#7SpjP{cA1>8qFS}KOjxJ)zg;I--!Mg&TtB2Fw!iYk6()=3qYGq? zBb0lU5M$x$Y?WpTKrYl3qcTWscJ|Z5C15#nq#A3Dg=ZVwJ zFv8EZH9MSO9qdIZag&E5Ip@GY)P!Y)`zOOnREToYMwt7NhAW$kLPXZo(J;48$PGvn zv-vukEca~4uD4ps$>WDtm9wp_o5r$M4+m}6$#B%p!($-OZ?~#H;Si}T5((VFa8fx8 z|Kv8`?&qBLKs89C|7H)TUwP>CYQcBq`~vkHfTCj=@M`(`lu|0hztJ|`-K&&s8GEaH z9(r=R26cX{Oj4_}#fY0|_+8z;9kV$SLc&TMhwvu821`h=gjCB6g*(;}9p zG=>n--zWBuPDk&*&YJnKxec%JY4T|-i$j{I5n16b>a;oTFKV^mz79{MvkFDF zFY7kDc2or|oo!=rr2OR#TB|(y_B!`%?&;`d{n2A1_B{BsR&!S*&V$wOHU8G-63@^H zOTm(ZYRthBe171KoVHbD>T*3w(x2*R1~PZ(jO*LX0EGSaN6na-1Pqb6M2_0zj6d`a zFSZH`UP{3-wum-1J4sGR>TI}pm|bv&zu75lW-kEhl7qZjq<#FQAnPgBKWS{qe-R+w zzP_xKUjKWRWL1jh61?1cyT<<*99>gV6X%*GakoC)e!$aIBHoVhtmY;$#C9}$XeLr? z-)o!sR?4p?=E}hTcvjiad{5%<(RGu?>AJN=xEa>}D4Cwlz3-4&{wHSmsIB#xVtuS) z|NZr~>qASB{jwD|@s8$fE}B6+w}!?0oNf7 z*L6Ws-gbp^+j*aEX^Fg%FG}|vxxVK(+}6948%R`0MmYO`L+i#QN!MI0+RmhK>~QR_ zxG)}F>8d86=VfqnN`L+s8B6Qi)}=$DiG>O)Nqz@6Xfa1IGEo1H{6fAo@r#tI3=M^~ z_7#sRmRfYr(n(EXid)PBT?6eE22J*w57K0=frku{tNl-qDpj*}xLpi84}Y*g_2sR( z*}QN=zMK8P`E>~Nw(_`R+sO`;Y3GRk z0LtZEyjfY=hB6HneR_HOd4Z~%v&o~gA=5vTdCnlS`4V&~I*ei(T=m}XJhI97NR$=B ztIsEq1eS>8EoiB`!)o7;@oxBxNvQD&1EOuFHkrE#Zl%H{l- zw>ztb(crK0X361aP0b5Rsc=b*<$A#Fq9(^tPxJt9A zC1nh_*#=G16mqXxr+kwdf@b3z@t0``M3mzj}Dz^e(`-c!v}! zKewM4ur?K9l307GSHA%gTTJ=3BVNN;6X^JHteY{%?G+e!<;T#N8p#9@g%LKM&YR;d zyhMuC1A>I~nKFp}%|u1k5*30uN|CLni4#($)em8Yhc||hG{pl?xuQ9Y3ri-KD=j&i z?nJ4vvj%=yk5lYjwhJzf;?$3p*S~=Aem9LYnrJ79dqeB;!eVVGb8BPL( z0%KM|q&8aKArEz(U~2IlLLXY&yV5ML4&cD$oVtLf?P{;;MXw}t3e)_mD`&5rdhW#B z)=;8ZFD}}q5{@RyB+=$>=rdhV~28U`Asg>|AqZ#!ZPjm#Mn1YRw8W`neH95a!ia z!d*~@C1JX7*POG?Tw?U{>f(OS>c^;{-V=1M2pO}2vCp98n3P|jwZUJ{@93zV?`fu6 zVinNaddO@CM3>9}<)k|X{%vNYpovUZ|8a4u%I%%+CR{vl6UH@}O?EfDP^L38n$DULB8;&Z)&Hp-=%JS-#V=+f~!`^wZ}#=k$%%P*cFirNjjQ0QgFZ(09ld0RW%?urZN6be2!L z|1~z!s?q>JT>{?22MpwIA*=UF)~c$2*T_CL044Gx03F#wK|Yko2LM3LNBut|h$P*BRT{^SQvP zqQ7`je2Q)%&W(m$S!0JgLn?S%mr-Hl(!8bBLIua0!McqtG;@q`5Cw61tv6 zJPtZcugdOfD#nZtp4?Ugyo9_~AIBt5IzPs6hzX&_2ZPtJ|8FDpg=jaG$!ejTvnpb} zQ~;*_dfKr{Nx9!FMx#(TC;6Iri}_nJbi3HUacU_r?Vy%tHF}ptigDfi!r@EHoI^Gz zIVyT0q(!Zv+k;-JE3`ZE1Le!tWP9{?~PZl)XhbN5Kil#DfA2m%DSW>l~ zf1-PBb0MOQXvMJ|H|vWt_Hlu?wmVDKX_;g;wHOc&lw_4Xy!qvseBO{SiP>m%u@JDJ z25qBb$0Qdt+0xurw(m+ayxf~An{sGg7O=fNUGHsL@jdupjBuwgGB#fRUQuDE(lAQ` zS141<^;P6i%@=f7&>n1Y`8!Yvy;lBIvrzk?_q@@5w)18y!?d%*tS7WtUGnjgP~!Q) z4XE80pQ1VS=_?L;nx@DIpX6&B_=3$ll0^xHW*==A3+=CpqshvVaOL~2fp>ekpYf># zD*SGad+qG)BR!6neBP_7{vtX&8NeJNpQ$wM3e=R9?Oi;Wsq*u?+W+GOZukBzjnxq& zA-5gJR3)ZV@v1b-2JNPKF(1b%0qwBPWL<(i)PABA)uZ&78g1|gx7EM^w`(Oe z@1WX?C=70(#19qXHnCzLifUr<5Djq-iJBhxyg(s=cG>1^qo28lCKE$N4M## z#m1bFd~8PXPNuM@IT5i*FX!q^&6}o_%hVt4oad>6+Ehv30B2 zC3LQ)DlAbYh?;Ozx5~hS@ZqlQdd2TVPb2*})`(IG!Ty%_4GrSWx~KN4tBe*2RV@{;|(qq}(ti z^CSYAN!fJYVqoa*D1;H{`0{gubi4WDPg~UtNSH^wUVaW{Y*FM4oq|o_TH!nmffEjg z|6u+0aEL7Y_WyLwm!~VBWcZMowH4$MbM7t>m;=adr_im)4)SgJrKTFzQKSKk~j@%>X-uyT7573>TAcx z86&w^;NVPwrT!_J`*amolZ_94oI~5#_E}N&TbE4h>jvs1QaV0c4X34QU;Nmgn1YR@ zvSw&I!EPZwbu-3nyk8_m%d9Iz9VbzV5wGV-(+r(DJiG$}9(hT#O-@>Xs5y9JIJVzQ z6qhAal=VJCzFXEl4g$aS)%YA#HFvg-a<;v_B280P)0yh*c~B?gH1Zy+ZaWsC@|y+Q zSq-d6S{RdMJ1&?}xG5GZM+ha47G9t?_}(mgot*cRnZ6BG_ij#Ue>au7#I+Od)+@YW zl#D@YWSpe}INbs0Ae>Tcc0aXBVxeBCSj zr;$K(XUOrnhaeL|s4n8S;y$G+TNfzG)mXm|>j!lU|6Tf^CJT3quZm#CTJRtm7PeJ! z{W^4N-lxlJGq!{`uFy#pQ*2X8i!w&DljxR}r8VX-347t$sAl^MJbK;VFr-HD&vRVt z;wQEkJ}=tA-$z56+Z7dIqHf=NX1ATO$FWRqi|wL->Sp_2xy;{0G<9aHTtn@K%i>2F z93)*JHCcjAD=1+3*cK9Ip$2r?1tHYi1AXqGrw6T@1^b#Va~7kdZ!Gg1D5DrvN8t3$ z=i5Qa_#bIwt1>80zkF;Zv8Vqk@9T@6v|q@QzmpqQYc9xPh~ET>E~gD8iw=(pV~{$u zvF)Tk&*a!c+fZeXBOX|?;ad=2A#6up`6nSu{9{;HGtY)v@p3X+xF;pTHC}j@Ja0&i zAc~MdeFRmuHH!B2xWjcnIWS-#mO_?5XboV3?V8ulu9f{&UU)Faeynwy?wvo;dP(h8 z{5dQgVk{h*`iGv6l*%Kpqu zEj5%-Y3yhSrWH>m=y;%%!t|?86wk}ysK+-bO%5tAC-KoIA0jff)A5ucAHJa} zRS#W*yB@A)O(kDKo;AOTUR*CQp>CoIqZ~C7%T`ATrZVD}fDkWJ3P0)9S?^DOLvtQK zpMGnigtZpesE=MTgyV_^uC;6q-&yOcD#SE^$$z4HYl9Q-&R-4l=qXv#KOODTOf5BO zH3k8K9`!5hgYfhQXU&7#Rl5<~GYZXn?RB+~Uu~|Xp$oN;+1GfF=Xo1W`-2ez$5#uI zsHd|vVO@b3^2$NEmNu#5oS`b_dQTxU&6#FOV-1X=Tqks>$)*}_u}qpD!BX*wY~-xQ zouFyvEM`v7k>m4jOe)Yl&j7?N7ZfV^%u+5@Z*`z`sH0r-yql-`~V&W(JB_ z3>#(2R87I|0-`Tf|5yqg5C!*z|REetnIViq}ClJ{bBN4_Ye zQ!nPuR_b4v%~l)V*kI98hxik9%gzKLOZDPJc@dtH%l9`vd6}=wCp@5gEcKQ(CJnX| z!)oXLr8A=j=tDHF*go+6&GIeEn3%A)%`CNb{$V1(o_S1*UwzRe_tZfTXa3ajHKM0$ z*e}BYod*c66&7c#uME`+Xz-O(<(=hf#l=b3YxUtwM&Zd^7akWH36em06{-u@cqwAk zTd{|#(|MmqInLObS&ntXw+}K#Wc%{T2V4>GJ0zk}q9*5!fix?;=Xd-$ zPYaRcUj5wO4o<{FafL0(WEEB+D&4D}TGY2#D605tBAfzApX>s=Ly>>>4g@d_p!C0r zww;nFmJSl6?eR`94)4yyrHa-WRmy^Vqc~ z@tZb%nlEX&IBeghJbR3nD!^VNn4`M8I=JDT=9;S@vzq|hKc(b7SlTaTJIfcKo%+U0 zsSwc*4)LerSNW<`C|Frmx#=V_mO*;zGwvjxZvWyu-rsZy=~=DrV5g#ns7w6YBwIuh z!Yf-9wl@fVsZQT9{;Tb%>PJv()YvRw_M9p;SJaDE7Z&186)(k!PDx3*Qe9Q`h&l2* z061^>;4H6VOh&w%++lZpI1kRHsoQ2=>DT^%sRUnBh-RIeuD;<=Kcqw~&sj(!#UA7H|;w@`6(l20y zgJPWCQEe~5anok_AFp)0kQX;_BdBD0QS>qsFgML%&2#$p_Uy0U&EdRTOJlT%5>!vxuL1h89seeKZaAUL*BSkFh*ZW4tZZlA44&2~N2{L1B4Yh3-1#T)7#=2V!#LvdU(CjpSd~CKFwT6;UY}gYr#6(VaY)$eA26d36+A=x;1Oha8XrT3539f7sh|7pcVHOnuv%U zg@F>+&C|0rJ{zgNV3^Q(uOP3x5_o?k+9Pg0ve4co%hEyS_AdeAutAjT0C@zZzlbF-Cg*r+=#=ZLYuWtP0a+}xAYB-hxJwJAE3SXyc3uT!Z@q~_Uoc1~uRL#9$gNGE` zQs|>`2DD=%iqqAGF+NAl`-jC~pRRu-SOW!pNXeDNc(7ldvL9%S@jk0ys&Uptl*no5 z2;nmoL=)mpFQt~8{hMj@59Am7gifYaTInI5-873NP*vvl1shE2b2d<&7Z%mF^s|&> zqES{>EBBg5Mo3g ze|mcQwB8$efTtM}*Gr?mmYZ@G*7L|Ri={4DxJ~}I3gozT`gf&;e&8}KjV4-4joD~1 zrr0X59D@2eJN;1EMkfaB>uJNZ{z@F$*Q^yLWi~-_g&XadfL>bUK+XS@)(XWAP+$bU zS^9a-UzD)rI@U&3(q-t*u+HOw{nBoNKXE`oRwwO#S7yMff(S4n>nN~Mor-Tvwxwmw z*2iZ(>azeWCr3pQtk1zG9g%ZS*O42p?Q{}FO_P^eN{#))9KZV^LJe83jc5!Pd1*p$ z!2rkV5L{IustQtt%i5o>vIQJm3k9Y7c_)JbEv*%dzJ0)s;bt>|PjlTx17YAq5p?2~ z`S4yBC?Qr@*Z_wwHq5CE4H>{}BGGA1vI%`*JAgu58z+NnXD%-K&wm!_H7>9%kZ)7_ zNA~O;90huOY)A{Isx~s7k8E=dfsc0xCVuf=pdt$D+O~4}L{yE79V5`#st9xc;2?vg zw*;KXgx>v&koWFATu_r6g5apUEJf-G|KG)>HbSVZQh+7MM7obzzX4xJ{jIk<&e^g{cD$Zsor;A7 z@tfm=BuxxNy-(MUW5~DynNtYYdw_}7%a_yaB}3~eofR38-3SaWiQE6|7wCb7vcoH{OvJJi;|UO>o^j0L-RgwErEGY(^2b zxqM8}zX=7p4ofdz{!JA7{@kPzDzwrcI5K6BQUvGBKeM&Rifyp=#t(0C#zn`|pJa z4@(j6TpF8RC-Ko4okIQ(?CC#$l4A57ttXe_@m-)~J^Ipn{c}0vJ-K*&BM?BQ zONPLhG8Q=Zz@8Y9-{nF3kRvIc9y4(mE$y_~! zBDP{=kuh#&R7r0SZw6mQJN!cCqplR-CZFqIwq~`QtLp(yySyg@47g;{gO;dq#*FcZ zm=|_oFGJbGpr%O$Q=<j+6^(UkRKu1nNvKMz5MAzlsyeHrc-zmY_JwiD=ZDWo&PF%-0|`Gf zQUJ2(<9_(Yzg?A1;f$BPR&o`S;ioRuDn>o>uV^p?#>RgK{et+@?)N9aJ5@TbbVti?xg8L7-lZiJr9RkSTMH!T@SA!;S1WJRcon@`Ufl<=p)& z%ehr<@ptlqp5C@s#~)-N7Yt_zPWg?%Az}I{gN5jG!l6Cq(@j8@cMSgNsLexnBv0^o ze%O(;smNDR$fw2*wjdO{+b!ZNhxjUbda}mz&`=@ig07`(`mR`EVOJ6buk{1%N6+IP zAPW}i0a8JY8UC(iY`JAN5m>BI6LKT9q>!T}zb;N~#&Fk1vZb24>mxt^YI*-Wum(12 z9@1`#Me>{L!SYcOjjvIz!b!~eA~>Y;tR%9Xuf%66)R7>_L+5U8Q;IzqTaJ`FMJqqf9BVwO=)zvB-+^zpV`Q9)xdNbB~ z>ASsxXyW0x8bj)XxHM|l)r0P))F)U-FV?U(!@55siJLkoQiFArwRj7zxIJa9t@}zO z4^|<|dK1CWJo#85nAjTsTV+~6cgx=r8ZXxfH0YQ&5o zUch&?yJ{LX8yXKQKH-ZzF5VqzLoNVj|U~ zQLA&;zUD~8y7bg;-^;~D3bO6WT9j2!^zd#hI)CR20?|Wf{-$1jH)08h==bPTq_TNw zJ~3Y_GMOZAmD!{#F2ZxO8uV=rzH#^@p0(xdc(KrEV_ zZ>VDNZX~7TBwSC`DZ~)%tLW`oSOU_S-M7Q@Ls)==@nlV(4s9gwSMrcYXgnmm+MlVF zLoS5T{MAC#e$3oMBW6 zVu_p&E_@@|2dsfR`3+y0SUmo4;^1&4==t%PlF#<{ypR1J=>iRER!Lu;g;{~Aqn-iO zJ-*8dRgkY+&sYaFz8gd&L-*lcL=bX4L^?>$?HjjgJ%q>8G1Op z`pS~&b#Mz8!Kx#g2K_}S>ntXI4`+i3y;dgAsTNA5HAnoRtwE3FMe&pg%#pUkV6@D2 z7<=nhBBrfyX?wdRH*?Vk1=kNh{2kp)8|Z2{)#ba)b-tzDdbz(K+Tq#`Kc+ppw2YSJETojc`{$W!~5P>jFOFe8AchR=SYIR z#zs2o)P6Q_vfhz-FE^$yv*q<-cSQic=({I4um;l<#q0Rs$_K(xylLnrZzSl%&jQku_@ zX6S5J$5xnXhW4r}N$$u%lDG?zch)A^d(*tQl0j~Me*OSryu0{mhTs@!C)F=}dwwL$ zYW`Fsj7dh-u;Kwtf#mwI#PI!w>B;L}zH$7QKDB2Op8d8un1c70p{s$aNc(xfJTEd8 z96Vkv26L;zLsli9uQt(}=fhUR9@X;0^sXw7V;sFTjAj&HoTiKKl3z}+DtQ7WKq5`{ zNN0HR-+wa0Yp(Xg&WG$Rv0}my)m!>LRnz;0*}x9ZBLiXsNZHGtR)8jVG6{SJk`Qm8 zgm1*gZ4k#GHQ~z^Y~L+cLPh7ZndBnWvu>eF`z{=i9OHLdmcLll!+b^ezQ5^jD7 zvt`wKQKS|)Mono_Wgn1eDPAhL{y2B?_ntrDFT^A0_9&pWSJny`EcrB$%BuDBH&si` zhxW@*vLP#)eAs|bYU+mP*EBr=*2%Q0u<*|gU2l0u(&`*zAFg-xrc z%iO3YytfKQTkZQup!TDYXCHNl=3wJYj#*2e6Iib3)-PP>_CmV1xryAQR+lqDo_yTq>Jf5m|vz_GKQAsTUXMiAAZ^Lfgs19JW^aJk3b(AQGK>YHz?9FyGaXM($Y;RN+1sl-j zaf0NMC(e3%T|`qan)))|len3W3$GbDs|g9_fGLWcY3sh9hm4eP5S1HA&-6Tr%Liq6 zzja#P98THUC=t3jY2Eo6;CH!O$4hBf-C-2qQ5-;ZM!i#X3mw0;ND#jc@mdYYV9svX zgl{J|tiad$#M7#AFYR7VDx-eSn7o|LNk(EAZLi>n&NyA^cG&{+$cU8g(sl6+VvB&3(8 zsEnehOUagb8_mJZG}D(eH(Ktjc1X>gJCbP7|H435p@gGb1OTyG&mNj6Qn<+!@z`(n znzzcBa-sWmU7A3UvS}cM9e5IfyrP>$BNRJj#N<@Th5S_$$Qm@`XjXMv$u2YnGRwX0 zuOQwZcA!#nrOHmEzOVQ3Mw7leYF?G_?RvZxrF8uDq2(r*S?@^TRDz*}IbrS3&w4e{ zqlOG_jU>V7rJptwR7#dqby@h|n1mZ&;H3T$E5Z3*GYJxl9&5l>H|OODU3B+cO=OTo zEcsvj!uq>;RgRRdH0a1X&vxvzlkqH3r0uW2ljAmK`ilL1ca36HcluiTrE<&~Ia?Lyq|A38_vjqix>S|aZ2j=oGaFPX z%j~iE1|(N||&3`d}pK5o3V~i*}I^g=p4;~4>;#)RE3ahIfO&Bb99)-MjZ^;{) zNeU~42un{pQ-nroS~Xa{hY32y&K(sLfru2alOo=s6Q5O;ltq+9lz5c=DPgPs>(zC? z9B^=OK(-_6xndh(!=o-0kd#vmBm^0_Ak@XW6`ilSnxP1#)t0(^??D3eVOcG7#aC4B zKVC8SwwKeIv}-5ey>)YLykc2Wkqs3fqonoSEpTD}>b(Wj-!oVz~ExR^%p zmN$Gc+wE}{$^JurE02tf{y0egfZ%cGhNlNCG<;kwEO8uzTkM^dl{2fT2}Y$Gb+%Lr z-50r-KNqMCov&f15}>HO0e*Fa63<6=zso}@tWg1pa;~e(1tb|A<0_4%{MuHG2O%}$ zIejA6yqEu0n%C@+uGA0Rf-kesK1IfDBd-Q&$y zR|Jw2(f|1S_lNohzh7Ja(sdL_cy=In6Ht&ElCo9cjLsei>Rh6@n>_!vx8U4HIc`nR z+qSB(@%INEtxF$J>}*qssYp$P(P#3TtvaUzrJPs;I*O`SYcjGbSG@-D;Z!%IvF||0 z4CEA56@jYWe*h>S>=>tD(q~NQJAo>W*#rl7o_N6DmJPKnWcCcGuk=b}hfARw8WmJq z_KQ{_*w_!K-~Ae?vBT#+FE-gx7yLc{M5DeFBE@-nVLK4RM6ZF}sdkF~Mtl+Ij82WB l(Eb0L|91!!xlx}9b#E!L1cS_I{`*);Nlpz~En^n?zW^hSBuM}O literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..97ff71c3b43e5c59c1a3cb7c5538f5705c5c8f1a GIT binary patch literal 2651 zcmV-h3Z(UkP)HtZ_aS$zH?{p z{C@Krcdt0{53#)7JpI$%GlaiG!1DN~4W2pkXl~l1(GG^$_ zgue8OXG`E2X8}(6grh6P7mXpK8jc&URZ7@mbXCy(UYC46+0az(2*a5d%4P6XDH*RZ zNEy`6Z-kym6}?RKRupcClpH$EMz^&}c$P+1KZy@pV1;-MO52V`T?iuvVrjfOlsYsgDL z<9T|3-hbI$)1S}dYjj(eSV}%Hdaxl5$>wIu$n2==8Sr=Gt2Eg{O8jpJm%y)pd%@ib zMA=-@C@}J$f(BPcI)iz5+hZOJ%cHp<*e^LBPv`V{`8Y|Fy0p&-niX|G*MvI zt%5TR^a{E)yQMg|t9CQq9g4%<=9F?SXbPFo}kKwdQkn*_Bpe+OFb22^eVS69Nh^nUX8Dw$_;X z0oYtVC+}WIhLI8`&YC@of+XUq3V){y`f2DFUEN4+Q-)o>C|Jb9u^l}q*dtztdNX-? z{^T@?{8iaG_=}@gCQm3AkfeU^5)&D1*K+35@JZ@&Fy7)$lfq_{*S80_{3k)d;PE-w zU`SI*NaJ#QZSxBCLG#{1lOw70sqk+S{L+vHE=-q1s&hNa6g0tKw6MS>j!D3;X7rZ9 z*Ol-$O8hKDN6~9&4l1dC&X{$%e<8v9oVp}#^}6u2clFSEbzr)~Hxy>+N}_0=dKI`6 zJOus*)XnxkP;eoKUafrtHj?Y0Rq!%$yQ|kY^ZdoRws$s%LFOSB2aB&dt6OqYQdyAD=Zj*_ji{r4m0wZ`d| zXzcKECHPJ7*~;TX@&&!^Ftcd=q7<%D_2uO=f*@Ydx_CI5A-MKgTHWSR>C;aE8J6-NbYqldfM(i zY{?3IzI}rFX&_GM=5K#E7DHW6lLnpH^3HG!L__oN0lb?Y0 zW6DH&7WaQE5jpSUSp=1lu9L4s^09ci$JeJUK%K}XR!_o33i&ug;7Xut4r|CLbGYr zNbu@uBW^}JeR`l-lx*ZCaSMEa{Pm&cVHQ76Y~;2~mOGsmZ7v>!?>{h{ET0V#h|baW zunV3+`0hnC=Ji|djMJK%dfdDp`Jd{Z{R8Dkdi2i>F&&W}M5vGSa_Bh`9iU_AW}$y( z^j6(U8Xn!IM|>xsvj_Y&*ahG6Hm5yJPaFt(_vv2fIK=54W&;_(_*iDkHxK;e96MQ~w$GN&F3e@f$cRW~sx#^i?~o3N-38!4Ll8 zRW`M4ZsaPaE>_tAvrsG`>vk?)izUtn|;4SV&U zpw82y&j%zQ0!0s=G{53Hndk~eBS9~fM(eONA^8UViz}*gf!c5g)D!rfX}nSE1kh9R zB$z_>z0;@(;Ecf0`cC<%Bh;}gpgzC29^3^^GS7FmlO&>BX1UX70YdUv22&XHVa@{5 zid~ZB?le>C`lZ3P*kW;9#jImfv|zMP3C27fxhm+2$0mQ2lSCa;Z+laSa!hrK>SK1? z&LE<##RAd7SyAjL$C(ltv*Qj08H{#?1K)kDD0Y-%pP$9bnMt;T(SB3!0wx9W@So+` zB&XcQ`$TW77LnAOz^_@BuGGG7@a|yNyc7$Je*SjztUe>V>>7sPJ1}@Js6C>Npj8Ur z0}g#sp1|gPOxi~%7Y5|4jrp_So0A~-6Z;DZZ@emjuK=S3EbLKWVQVR}i`I}zdc4n) za$QZ3B}FO#{mf9mD!m*0Ja{$O`T-Jk9b5ZP)~Pn26@2HhO)f{zmk&_BB2et?j|RM- zQD}ncBMfazBG4P7RtNP3MSnk-J0VdF&4F6!Ujt^R0Lf|{>B=StinYHluZ778u6<{8 z$fw^xeQ;=CY%~I+r!MSKK&LU&jj+BBAenucX5HFno67N{W1g`IxAIW`~`Y*v$|Htrd;)xZ0A({BNj(WNcdJ5YQNsky>V_gQ?iLZ5tb^wOYqkoF} z#sM1k4lp-j?n2hN3qk&EFooMUP7lnPDJ}nc+Im;lTcg{+bt`muQK#>kGo6iRPDgwh z)Qj9M_&!4Y98YKZDZKIajZu1hwT5>_?na_epeGg^mGw(Jn z>_CmgM>3suX5XfT9jKj%ewtwO;bG{}4irmr*woqVfsNk-{|DFn*fW=BWheju002ov JPDHLkV1lMNC3pY; literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..b05f14bce84652d57d7776bab0a068164a3e30c6 GIT binary patch literal 1920 zcmV-`2Y>j9P)kVdXEwW`=R}oSv$F)z!DUtGcV- zYu@xtZmR0mz2}~~{d@0q&5VrHmH!}x7^MzowB&pZ9WZf%lUkHb53>|teaJ-BeR}JD z(qjBW#-Ik0V>S|wa5|q0W~7qe(Qem+oMW>Fq}^SZfxHSG>`C~qwr$CnNCk2t4Wd&z zFgh@g8^ffqF30@QLUisZh?!_q!lS~YlSn3Y`vwwC*e*t4s=(y~8zqAeh+;AC<4Yg- z&ojp9uK>rK4%P(x?=1t|R_Krir296@oE_3b$!vC}H^Tg^cIsIjJ>|HE)98=tK%*U1 zb9-oWz;tG-0=j;dIUObssB~m>5IC)Zrw#Kv=-*_FGu>60kue~U9mIu^O{YrTXeO5J|`w;l(S}ej$=d4=_qBJ(c`Xd zX9aMaCZQLh8~Vx+315fKv6T|Tz8ji~jiGT$omz(1gK1jp+@wATd( zdjtUYdY!}N?sF@7(iL3O{zTz-l~o2upvFd<`|(BN7Cs>ekUB>EGUJO|cv#gV zX^sR52zgJFt2G#3U^rWC&kanK04SEUfhx(<3) z>AG~H4IQ&2>`R$p$bC%bNj(TU(#Q2GH{n5W@8v}C##uon z>w7bCdca+;!O@Nfp(0>P2L}ZPIBR_73J6QSKwr?oL4g6z8XxTiS6J?Xpd$hn(IopH zq!ZNz7Gftk<-dp=You7$1@VXE+>q^07p{xkx2}K&?9N;+avwB6!Ug%hYr<*gIicjR z)2ZSFa1U$nA_(zMd}UN;aBv zRr%lin(Gr+St}~ z$#*EtJZ40q{CxE%yvF z!8T>teTGvi_Kf9hUb%Gf6M&c}uzkLeByXfkRx)$Qx!esLHlDXyN>2?xww+g3fvy5w z1-c4!6=-h-@X+ILyUBiH{Qy)gZ3F&8gZ9>qA2u?-J6pvYzKva2;4M(|)rGm{A35)H zyx_NT&NwVK{fjcQT0(!jPx0E|Q}&%O7RLuXfqeZu;fBBsXVL*iUMVJvtw*ZrOh9)OVh7=Tx{MQ zo~r^l#kxz?Rh-Vg0xMAX3pMM3ONM_?^DgueC^rTVtMDz&*U)G2%lWTmi}WcR_oCle z1~f$Tmr=OdZ%BK4QoDug<2t$CxPr^}74rj?>K~7rrCBs^J}#``a;N(sDwP z7nJ;LIq3{)Y61*CvRPpK5A@Eaa#q0wpSu(`i{!~Pm{2Q=tuOn()}c;Zx*Bh^;E92G=bCj!$Q=qI~d zwM}T>g6&`E3($T(ZRe410?G|IFG7ptLHzdiO_4*?ITUVJ!C~f;b&H)4wlU}@&?RV0 zAs%tZgq&MoCm)yWvSS(_g9+b4O+dM`ocETmpgThn!+#U>ap+O#$54Ji<;!QjtX@Eq(d?%pY%k7YZ)%kW6=qj+HD)2vBB93~3qd6=900003EB3EP){6oxfw6nn=KH7bH#uoILghy@iDu@WRt>=*W)u;W(4|G1gZe1O&EtFr*lBhGbJ)JS}j5*8b9M$^chAm_W=@JGRB#r1{ z=3nhN*!P2iPQ6u9(g!NbO4$nRFM?vH>Bq80Qu4+EG5%3Lg(W38-3C;tIQ~U28I-^b z^SgNg*eA$GlFx?6u%OgWA* z9Gxl57GlUto%o15(8hZGO>K@!eM3CH3K2Yq87_4%t-_bY8p2yDlcfZPGx&)#UHZn7 zLShfF+geikuY+;1*et!f)Rqq%4`=yCZC)`NE(UYK9~yY_Q=04)^sj+mz#?!PNDk6A z5jrQoTYaHEk%hmw_&)726>RPCaHB#6b=!%;5AllckHWe=@tVJ0fqDh{ZUs0N4SL5T z4POTKbk^ItNj^?hi3;ca(rI0MTUI3rX%rN zCi%{xMA$DfKJ!98UDKJw!3#kp#^+Vzx3OOgHr;W(76>vC6etEDhz~@ur(_Rn3}7tE<$9On2^1b}BB*w=&SGHA%$1oEpaG9c#JBR&RJdc3f&(J^s_=ednBK%aPt0%C`Ihk0s^`7e{@i zzsoK*X(2dCvy?O$Dh!}{AR!$7(cTLP%1`{Qj;KOCEuoH+w&-cHg+s;JeYnOc4ZTiN zmxH2Tk0x^Bt_O)U8OjVCK~DP(_T;62qTKjz;W$GvxicnsFcA0!I)Ceb9dtUb9R&1{ zd^-3Hd`6@^ye}Y3}-q>!JQ$hIwzvNU%dx49Iad$*dlGR+Ig6%Bh z*SP=aNHH-I66#^`E+ISmnWiAy-7VxlB08%2+*J1ch!l~Pl;VTGt5=|2fqDh% z6{uIBUV+Z7K&eaWSXxft>tWNox|@M@fnLh`4txOKSK(sN*ea%9 zRKCaYT(CkzJ(;;GW2=uPi!2;+F@FeG!jOH|)C>LFIL{FhQ zvwo$DJvqB({vPr$0sch}j5aojg+d zV6%DAJbmNGG@c7g<;ZplglBw!D^FGW*xF8Qp_ttL^H7k{%`tt~ZF$|r8M0dLE~aCj z>-p$Sft!F{Q8?eTX&8KgNd{J2uQp5uuK?}q&z8O~gkqiqz8uwVaS%-eH-eVMN4Gy{ zSNdwvwhGKb@2Gd}EkwA_3gpaF_0^({rdmD5^5wjCzinmWNV*re7rYOC1EEVA)P3~p zsR>fhWvVJ5I;)N=vj|mv$u|nT8>pp!zG-%nX~BBsH6$JTqa2&l?~^#TXnI^8d=lt$ zjM$h0$AX`LFHd%}D3Zk%&96h_IpCmf*3%X@MJ)&B0$;9gi?Co2$@Cz60Gth;06N~~ ziC!-_qF{>dyHSj8owUQ@%QoH5-kO0Tb_cWlV!ZLSj61Rm-daHk4Mkk-6{cb6!nFiz zbysRw6Fj71BGT5~PW8%C28uc^P}toaOV9x#>YEa%Q7XODTv)2!a`}li@D+^p(57#M zTe~R~vpV?PE9z(#Z>Fc~&5*>e>!b7J0A)v~H__JzIt%NrW3}E?70yC_?M8>TvrY|1 zbV*AQM}n%d2m+lUyLQ`Vr%#@J0tJUQE^Jum`kE;CIZ#AZ)ocjHcCON9Cb(A(6sTvy zy%CbX5GX(w#rK0jpiR%Fcj6iA0niw50(cx`ZDh)3|J;mWAO!<(&`wuAdsZc_W#IV{6&^o6T>tO403)%FEP)C2A*R=Y%u*C$mGhl z5WqTWp)A6LI3X+2=~1|^ktwS&q`W$^Pj*8jHLInSFlh}6bRU)hS`ClGZ@`NSz`=D$ zWpqbv7LemHD4%tOiH+(PKAAF*fY?UWW<+N_JO{P|!poV?KA9KsxZ2W$Pv`3)&Sc{v z{mW#t(%&ulO#M-$0QeQ%M}mAV^0;LYZe}Q-@3Qpq*bG-zy3L~DvX&s{z^}vi1;Z}d z=YqU}_82y`)dVP`YSg3^@E$o#YMg|Amp3Bolj@n0SWkZq+#6I%=q#6`u_#9a`#F^I z4KoM?ovr?anEm~o$qtuctY2sY_;5j4(E-0yJ{6D&6PQB+2HIi*?XR6&AE-9d>;^Db zPy6|j+wq}kD`#^If!0{RQH#@W;n(2*h5$!tcL(`dTAdiG3DC0O(6l*F z8ZkszR0@a;0lzj<=ikSkD_RfGDG0V$0i9|>jFoZU9Adri`?HAQ^F@OP%4mIS&4K=d zCTDF7C>Sd`@`H{DQdZe-09=}if&L2kzR31uX)p|$)E5N6aR+Sl5~^q6W3oBQ)>L^v zpl>q;{R=IETBl!VvRZG;^(f~i4LPD$5FXmsYe9qIrObTd#4l-W#rGz%uCrS8iL?T| zK9l&93}i~|A2J~A|C}t*pT2K5pJ6+DXP{>d)OM&GG)M8tR=^E>Kge=&Zv))aAry9l z4rx&;+Jq(l``r{~U^>$N)l&N;=tfLWyUpABDii#4Sc~y~)5gw)Qpvoinx0_T$6%fL z=KDnS7s5KBiQ{widFbATjh^wowK86t%#(IitwTouv5#AxMj-&NGzZ!X8#zq@M2`HB zsSV=_dnyKF%Wjq(rt(zO6z}3ye@YIxEG}+PeV6lTpCh?U3V_!=aGK=87ptncAI1f_ z5f)Cm=x_42DmjiB_3w@P#V&z2TkxV~qKEB(*~?n*2WD%)C2uXTZMQhyPjd2r2K*Mb zcVz%BhH9$_{HL*B0qfhnAD6qU@Mgnr3-V2&zW~33W~*#*d>A&`Uj_y+lCq)KF2d3h z+X@S;Hic=V!*{0-)MxpkMnw!k!x|ZsxB>VvO zy;T@*;|kC!U)6=*$1Rh0lo=9wT@t5{+~@aroE6*8o&9)hA9&v-|AtS7{t{=K{=!s@ zE8vq+aqpPT>jx&2Yy+&vI@(u$4!#98+J>OL=Yw#znH>!JXw{cq52>_AeNNwsB-lo{ z-=sUP+Am|}SDOG@y@+}*d`B61Q=m;#6#7rA^ZYePA3@@>M^F1Gvh-spKJ%L23(Z zf(P@I1x)44b$}i$1ESZA#Z+1#z(#m*U$LNhAt?b+{&Y8GAB2va`4iL1_yF5|dn%(f zGm`TxIHTAjzP`N{1E!&0*!J@I;)fg0V@#gg7}`#3e=+8o*yvP)-&}mI47?n_YmhxH z@tsncKtIjqmp?HG)vacuy~W#|zD~T=`$@*(E^~@)g+3r%%#C_pTrmT!p4(=G9Pbkg z_9XmA37*Wyx7f8l6xClUCve%{?LLTPw9B2nO#GSmbD-s3Z?dy*HeG28*xsJ#`Do1v z%nw}9SS-BDfbsk07q{4cY|gPw{hq}pU@b0fi*zdo@VbA-89_c{2IpnCwHm(5<) zs<2>x8=rSqVRIWk`{WoXxjUJII|{@;Yzb)fjc!iPQR0e}C;E|;UOH^0PYbc_hm9UC zi&3h_bFq1cRxg`=9zGk^LQ$_I7~P4WR~7Us#~r2&t@_f-u2&j7>5YwUL=?Z?@!dz)qLO&TR-9g;i{HhNP1opaLaV-~Lv)&56{cSLFv4&KhBGjnf#D1cXJ9x3C(8`5 z0Qiny5%fuZ;A9!!KI9=#4fEGz5^+XT zezQWyV1JYt@SSyo!{^3?pH!Ok^>zNIyq!V*Nu!PE`l^9}&3_>k`F*d-Z&ukD_?~F+ z>XzOqVjB}6BHiDg+OI(|fF-b=5$aaC2_0_&s==gg<5MoGNwt-JFl~>@o=v$n0VqVD z_Wf|Y^V}xPOkf`)>5XgzzS=c;r-@_2^a$VyIQb|5{hRRJuy&7j!`j}`Zs+CjXWJb*^m8la()%p>we4P5bt%`iu>8t4B$eY+OrYAq z5|ifNEv1{2HYk&uo@Et*9}$W zxlFh9C;H4qVJ!LMEH^HlU#Ct4-0XsyxV=qeob;4)z1lW@O|esnk8kSMt^R>!RdEEJ z569~*-P-g#7EZ+hrwNN+*igSO6WEXV#L&YrjmeY7T>7R#YODnv&iMm=7xk_JDA56% znlKk46FW~}zvB}xf2qI~`IE%ZnyCn~(*-iIbjbmr$%I)PYa37CpyCtvDl5jd-Jf6* zB(?mwxY@LyIw;0@v70axwP-J;_^qWFnEIa2#1H!7y87Keln8i!LYJ%RChqwhIVmie z6laZeSz;vrOz3jenYok}eJckHgycYEAfE4u2cg z?as?^9ets7k{SmR>NUF~iNvEduI4-`F8}}l literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..5167dfccc32662dca103140e76cf04ff43c684f1 GIT binary patch literal 2950 zcmV;13wiX3P)?6x2c281>QQXw?*qtIU%D;t%Gzda+BKiuz=g=Q^IvxH}#&oNX31xg< zM>j!ZAKJQppGSbfzo3;A1eyh>C;XU#Dv+ZyN&^9!ZAfc<2XqHI{W)rVTTXVsAv3ss z>g4)Al-WH}r;{A=n`Sgm^^xyX-)v5o>H9XT;zwVyPtqmIHTPBp!(&nzrn7Y;Ft`!mYsF_LSzNrAPBBjDHJ z*A>{K%j;ALeml6`e5_*l{l+r>rz%K5x6=O&92UATmH^!I=5KcEt2JGt7Qf_+&IL-I zy<-8e@9r>aw)hzOPnylwOEx{NCb!MVbDmq}33jUC4NL!3(=}-SZT{9~zGzITfF{#! zh$-UJ!p@mZ|D5g$XDW@D=_eRv#TNiNJYrOym<%~5I#PIKXb|qGN~K8mV9MRtmL1)Jt^Db*dl%8?`ZG}wO{qdT$&J}S*tAb`;f#|pc{VCd(X+;dBi z|G;JRTv>1&Uo>aoOjcXwXSTwT!(WrXAp_ECYP}TxyQkZ?C=vRp;P!S{Tck{{R_wiP zE8}>Zk~)em8DjgL0cbaP1t%i9bZg4Dc|MxnHzzMZ>2oBwWga$t)L*F?;%$;2**;dmK^+83O~_SC;qh%7f;9GY_aK%z6ONJX4e6ZRh~MQgP)?vWg!4ONB7r*P!_fQ*80Uxbf=*TZ_5A^q6tmlFQ^PSq0H zgZN!n3Vy2?qa(+W?#lt33J=#fkWF9;*V%}5B=$3cI675UGm3u+^u=8QEriEHKM14O z2=+1J0-yuTW1)33xgdO=uJ98W~nD8|kS%|_O8Qr~X)UR&}UkMC;d ze>yRfNklFlz+pJtctcf5AI$}8pzxxnuesz#PM`)cGf<8=7cT=S>5x{NEfWPPj05O7 z6$mXViItkbou8n4*#S(WBr_G;61dt^cVagJ-3W9e(2YPh0^JDg>=EFLehFNEU2SI< zyes5q!1N-R=wUeX=Gm@L-!54L19hWD%%g{pOP6AH$paZ=Q4G-a-hlbyeRO($a2Vt< z3_KSDbFDv85xHm$uIE}?|0F1Sf2z@n(!sD69ra_Rjj$F9)wW9HyNZCB<=}z@S^+zy zz&2PlMZXPR3~z&*klr)ZH{Xo0RE+=kBT4nRt#?~jM{LW-l5fnu6!a;$>0m{UBT;EJ z<{M3m!spwOfG?nXyJFGm*Enk<80||9mMG!~IDK6@C~7ir3bGcGW{5i(IsU; zaJV$$v;*CtF+cQsz#AeyH^%U->PUJpoc#DBDB$d|BqG*Pu{W7En!q@;V3qdXQ?;_4cj`g!{Z6UTp z1p6l(($VciPj2Kdg~91hviQikA8AMMZK^J{+(m8O$C23f&^=VD?Vz4MA^i4)_1?f! z6qgQ?D^$CPJG`QQ>dE~UwWEGhD@iyw{nk2mR-jHuzbj7mGwLJ+`^QnY=wIFF=Y?_5 zJrY6B3~^O`V#KCVWv?Dog{-!dR1?b|!J0aRw4^#ha#_ZG#lZHnFd==t zyHlIM`|q1sxPR0RFjgQLV+TK$fvfZ-=RR=yTR=N%THSx`jhX17Vb{0nAK(~i@3b++ z-uS8$T9*j#1|Ip%{SYOg$AGgiUe%>4(0gG^v)` zDprgy+DqbvfO)Pav+|i5VPG=v;U+JQmV@Q!n*2B7Ek+PxqKux0wqXCF~cN zLXL*7fuDlQNN3G0@Q2%|g*bWw`5b&V9Gjq{PUv6!)#N#S_qL7vU5su7cA*jA^wtad zUx5Dv$DS)uw@O+^(}Vm_onZi{7q?%Ad!bc0X%c@#om`a|0=)zFUrwXD(`XZ!&nhY! z+kGuorX@4IS6NA!rE{F#gU6rYvU$-X*w?|2!9_2ZW2#Mh?3)1(!OE|Gj5Oa^!1Q5h zXr%7b(R~~aAKgNzVr!B;6IQOw@zXa_uJg!M@6n3_ViQd5PrlzG4x%OBbolphjNa8| z4J4QbFOMZcw-%1g0kb6l+8@5oIjD`j@tAe$V~_lrZhRHK6V}p}Kk;ofGqESan%0E0 z5k;>L3Zpd=U>IHmYh|R(FA6=tUkRVw>S**3j2do&L()!KGa|w<@Uvm0KKC`5J+E1% z?V!nfK;+n-38NR?98(-Y^mgf&Q$<$LGwY*{AE&MJ8wlmpGwb27rUBY3h+PW$PaW^W zHgMvY^)B*kFR_kmGWF~*UFE!VCw^+ z4@GN9RHXESRM55*6d!15g+dV`7HLH(Xw>-XJEf@j!Nyus%m*K7d=Q`Uk^cU3XN_z2 z+561QnK|d?-g_3TyWVTBS!W)5_Ut=n&Y-a46Syjw1D~&Yqhh?A@#uCJ16`d{`9&QM z_6GPhHIh!o{DKFqK7x`naGd`@*^gBD{ zm=@^3b65lYEVvl_O|Gl%oIgkfN%jfCMCRk;qCAeprI;t#!yJ*nXNhv#SIm~AI2H-L zQ=VXxbnrix?CrIA1q$*+`%X$bzL-i-oa8A7OJ;V?_sSUa?V%)F=M(1Dt?Y4Zq9DoI zJdwz$O=4%OFMZn2^~~7!8u!B@p??7n2j_w(f(DP)N{aVoisfO9@1Ph`~` z=aFkpx9$rc2SvhlQ`kpTwzzWBn}d04K|?;0HQs z27vDlt#v^$Yw8X}+-HK=Zi{ruKk`MP{|30#*^PY%=90j7z8RrE_qJBNOS+#Wayqek z&$}DE6MP8NTdu)RT+9zlX}VUFWZ67jNqr(41bU6v8;|}5^D&*M>7YxzejuJCMRD+& zcw{pfs9-}X>7;q`ulI5K>E28s&sl2{bXE7G*2qXPKed8Fcl0aG z1}zpuLcc1x?ax}3f9mXXMG~db(2$>&M)2dAL9b}d)>IP-?#(g4h*vc zT$z`HezqICjY#(dxYsaiDRMK=wHk2%c&kV<42FW94vP8+`8H55IZMDj!B2ylyIl-! z1VdQRd2Nhvg&SoXyguR70(@_Gv8DN5tprt0F1byGszOS3;#avGca@B71d<-)5+Cey zq5rM3dG^l;r3(T1-{#WrG%PRPZ;OK9(4peZ!JlaVo%P%eBzbvPLY2bWJ9kFS#Ur zzmqd%de!-!?f6YOUu)c2PA<8Anx)8R5ZY~5%$UrGrVm_YYyut?rHZyhes%Y69)dPP|KdABOOK<?w&3sawxRP3_%dj4qaP6Ezsvyj_et+I9G(G>bA$iQkAnVLXM4@tM#3|Au>|V} zME{5@Y^%48jCTe6-UdZ?n9~=}W3xA*Ri8!c=K2o>U52xY5zT;SY^!N`tF;n!$O?&3 ziffg>(X-VTKwYf{_PJ90z{Qc!ra#KPMqLuX|49k~2k@OqZp44}ljg849NG-f4?^2W zWLLl$;egowY4*@I64?fa?v$PTuPbo1bp+iXoxasMH}Dll0g8=o+{_Ez&h@dI6+H+Y z_-bWf-Q!Zr_*>c*rh^%{bG{RFaUbMwf_g&Skr(b=#{9Sg;|`2FFz&##>Od!tho(o& z<3ukON9K4G^iWU>$kJ;O#;7(s>YdW#GsusF8+Z&g-!@I)v;dlP4EP6d&^>pAR)W@H z^kqrU_vs59z+&(jaH`-|2JY&0eE2_viUrs8>DE)&E(I60t%e-SKyB-K3rs;bUpm?r z+b^EVwHZ@uvLWcxj_zke1;)4td_No=z8$Z9u5?z|J++16nHx~@QVXoNhD4$ zSK6SeZy8#5*2??b9QAN`1Ka{WN3P1xQRKS~-%CLcA0jLxezR9jIZv_Yfg$uP0H{!$ zv^o3U(7B=fD*mUZ4jkL+NWRz5?OgXg3M!UsT)|%t4-A{`OI?DVrm3%PYa;^{Ypr2z zQzBEK?js@e{JJ>Y6gnaQ46IxW!RK?}dN2fi{OGympj#O_BKyyrt$I~ia8-7S(Uk7Nwsl|Zf%ABZ@l_C?1Y21_IHja5CDQ{xO30W|DzTpj{TpM&$T zt2i@$U6CR*pAagL=S6f<>FFFoYKb%S8?H=aV*eoV2714OjaUM0>sj8UGW<^mZI_Hs zrf;Ri<^juzZXfTI^V&zJcj2iA3W+r?Qgf!#YnbM0wIR>1=|>EHnM#E7(~*FiQ~o2@ zQ(RT!9>AyZwh?0X0`-a(1N{ICV+V^~uYIxU(Ni)1DbrD;8mEmK{{XK6SAad!gSrJ0 zy9;2|IIvqt!p`#9%who(Z*e0-NS|n`43KiZ6ubKVv8d zcRcuB;=r#=9Vq^bK)=Jsr_h$9=;fTsH?8y>TT|n#|iFoY{)ZSe!2^|gUAF=0yAv}-bFct}7%U7ZA^p|PcNxJqTaBk}8 z@YQmA>~rJ#RLqRi(||i8O-oL4tpUVLfNw@(4>6xn($qa=lr@aUs?!0^m>F@YPUnZi zMt-O-%$kRTot2z<3&0JLdsdZ7n|IE)JhPh8h?7D6S59oAi#pp{aUE1!!NxG|z_J-^N literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..d41dac440bd57bf59d383f32fff6416b5f35d3c6 GIT binary patch literal 2341 zcmV+=3EK9FP)rS+n<^J@d~w9%&XV z_ugxL>$2CGe`cRO``D*XN9YKMfzbTz4X8keQ}D_h7@*xEqyb6BEv;7QK0$q3kQit{ zUy$hgNk;=HBZxB4=NxB14k%?yQvGc`lJ5BzxviG`q|Idq#l2b>0_s`+;{-zZwD#uh z(;76or#Uj(354>1Cw;#>N(g&nm(ba-ydz>CfpJ3^`THjr`WnG{RT?U9TNn>o^ z>&ybv@idP-5$C3f=rhE?G2L%P=W26LFzZ03YvpiuDscQ_!+F{{ z6!yEUV7Z?&N@I)qxdo;+fU_SkK3mHi{h7dN@k~8XeJ;$tQP}MmkHlgt*+*2ktn2(( z;b0D!5t-OVuGV}6{rt>ZPiMXlD{{b=fq8#Bl*Z|?jQJM^pVBC$@i8`KFz|aKc((*7 zW1C=MI8Kb)*e)-fSYyysps7Gpfi9^4?u}fO@^PhU@lj6?*{s(YIr;-So+OfZ#gWK| zkPQX@YIGNNBtZlnYXWolu?-HH{qB0Z#nd`Rz-`P#5g+K@j}1Eg&5LFa)tZnvgX8`5 zuIPHvg<9YTDVyvoW5}kI4$iMr0ap5qfw|wMQ?_@y^u3ZP=Pk=%?G%`PDehJye^%_Z zyp}#3KQGSFUgL8LoxH&%e4^kuNGZ5mAoxsXXpobts6| z!KvOM8mM))5A5S<63)ir?b!JR$AV;x2;BI)ARVv57nY*eNMppd?JbhaHU?vY0iT>| zVA*2ul`-(Iub-$JCv37uR^`Akh6wZrIH4FkF@i_?Tda-7mAU3lN)6xE4kG)TBXQ+n zn0bFyg|V?7l+Ek0HX0XOx$F^yztFF>gUEhcEBC!rL6X6k4{z=qS)wd?v8)s=k1z32 z)W%j$HkFgpTB%d6CbCz0DiCFMrO}?sVfM$X3go&fsid0&{3lpyvAr6@FPGOrvH^nN z9;Mwfvo5l+>tjij@N+3T>oTOj^Q=+LHDlj!HvYI?^C`V@BsSetAh%5qy>CC5rn%Pu zkPQJR=N$-8G})JkvvM?41|u-TZEBo#0pm%#JHX6QR7v1Nxlsxp2I&Z=-;E_P@ zbyF&O7(6(vZnRAWnhG=(Xe!WDps7Gpfo`t=mUaAb(PZ#qFxQ>?!F*%15PWgB=ijmX zPz-L@%m!}-#}apVr*0L;# zvp`%bU%tw7696T7}x zOb|&w2`-`~01WHxgy4g_c%KD=jq7cUj@V-YOFfg=2l?Y*?>latAaFP6aZw+5UfGs- zim$r~8S}01S2lBucYx)jYV;&vvlGm1`@+}U!0&)UY zA)YLpW#or3z5+Y+G4IigX>RB`3c`oP`#Gc$ApTAx>W(3b#;-S)xMCk#SBCJV4+BZ8 zi|X>4lUCvhM@1I+t~L~!lfMQ$0_^(cz;hK_!E4~d7Uig3amcA2LJ>xQE&T<-KpO$F zMHU!2&Q8q$@7n3;*dCkfQ?~Pr8e<~-bFA{ck2mxsfgt<=<*0yOt9TavNnD*@YGGIQ zQLq!h%fVG?ZfIg~>ib!2Q9SN?@CPizLjJ4jDnA^M(79lq+2V1iDOD4IU2Rvr$$|Ip z`@laUPZEz!KL*a-I*eU=h6sEeco*13JfSx|6d8K{5W+58UA|m0+PR*lNl55;^*;sn zD?YeaBenQ;*)Jidm`5F6}eswUIork{n1j7i1bS?+A;XH9CP3cZA*5ISXjsC8#5w3 z3~w(MdOS7(NS%G|u)CkWs zUtb0-Ae)1Mu|1Q41;}CqVksbIU|?Fn1Q!Wez>HvnB&RHRUj;PsxTlL_NCo5DS-vYm zLq(47{Uz{urLdrufIF)eFN=C>$Kp9298C&0d>j>3Wi(#QmI&+e&|JD$K`LCqX^9Ox zm!FhJ#F9xCg$Z0rV&~VNx}I+vwd4M->iL`R@BDt}_q(0h2j|y*J04ZN_WtefkLQ#> zKT}xDHee%bW(`0_>b${tK@5i>RrqyWjXO`$a6O>D@x@wPCN-)<)|wI-GN@ zz96rWW^cGd(fnS(dgd!hUz~duN&cSx@880<&@h_@mS>{O>(*2+(RmkeF1%&s2HC8N zEU$!p3IBAg8tdFNi&rp-TDj_fRzH&;^dsiH^ZbQVc+EprOgVUGg~4Gld&{+&(tay0 ztY8T~_$Z#`t8;Al6`^FyT@CXV=FL7LwJt@E^cMbJu_|@G&ukg#I>DP?ER$O| z%y@sBbF1lz<;C1{UG8o;WuR&(G^78Wi%{hCX%z+se%<^m=Vj!s%o-y3ieuTQ#K-c= zv&Hv4xw>8ct;Y_{PW{FE&1FvSs5?08_KT_o_n*xAK4X7|w)9V(1CjGQBC8YF)4c1Y z0wzuJe;6)w(l+@|xyplO4S(xvg$sm7C!qr z_1c^7sVd@my`U8;z@%CY(~Qd851FvhM4T>Nf+wa2#Eu z9&powHMrUU$+CU9lHs{l=5^ zIPsg1mO=UADZKAa$0**K=9O)`^2mQRM`LcaeWmx(js?B`^HDZ1yV)z}=e+E<%D>xv zzZSkZ+AJ`8{+Gr5?}IA0^$IU|9nh)ye|de+n!UHCIV3S0zjED1dh_kSoi1KK52suS zU2&vZIp}H6yUQQt&j_!&;k}^lXw5fS(QI?&?CB-z=ZHN&Sk1q+HP9v8Ppj~lj_B?GHRIL$zso3w;D~~zx%E@PCnXaf$3>KBv+PnDB%jq4De?7ZoJT;06Z3-7L2^k!=o z9WxMR+P5?yvRIj6<@EgQ9=EL_;gZXm6x;+ub}pWDUo%qsk88&D?0YBNX;kl*yoG&Vo_*{`o1?^GMVt^Rbp{6|jy_t|eamK{=j z$M+>&<)7{`F8iJt@;8LF_V2N7{^utAqJin9oA(~k7XrV;YJ2S*xKAf-PBXagyw!j! qqT$W^c_p`^@s(U<5!(1%JQ zzw{vb5@{l&DHVa=N(0kwSbma-kb=x!3PNFKVWOe=3SYP1nmc>$o;~|@_L+O`wPwR& z_Fn71{%g%TbIzH)XP+}PU)InJD|N{x1y*0**QK?R86w0I~$#oJ|2 z`U+!(Ay<@u;!Qg)w%%@_OfJ?meI9b3(^~+#(Hs{x3|AC`yi)A+3I2vF#UBLK9s(z zc?lu-+;l{@z|`quFQE=h?o*@3kr|3W)loZkiH-4aqVLGb-ctx&z}`#@Lx< zb{aZ3)Hj3sPBX++v7bj|QU{|=ROe&p-Nn}&)@c1@20?Z^DR%UWk&6_zIW`q2D!_#? z-MDZgHv;Qm(eyV!i+S`R5F<_MMV0f$PC z!=*fQR;LUrk9e77-O1}4gDJCCN2!&oGWCO|NiMah(Us%fClmSSki&?y{YY0RFc|&r zvYTZ}0o z$_2=8h^=iv8T=fqGoOr$pxH{7EhC5S!IUIgy2B;#Jp}pK66kky8<1njG~|B7-#Yxob3_4VQ)ou(6e z!5$+VH`T#Y3Q;E^T#sse+e(329YB;l{mKciZ`I$1hik8vVDv3pg-atjQ86Ye;2f&) zZcd_sV6sMXWfFSL3-U_peN-{hnbfymz+6t(-Z!=B42*JP3{dRu?Sh zg8bU$T$BC=7f(!b-N0P)si(OPP z7>8@GIwm|#3iC;k6l zqd+$zZz6|~cH3D9+)k3RbMzh0*&N084ATD8D?eMf$J?Gl~XV%rpeb@0T-v*J2gxDUuczuHtnq7z$etBWT# zo)wq!8D}L5DftXr$LG@#aPqCDt{B;ObuYHhLjKBL7mwmgJ$9^cl3-q-w%5n%;z=!< z_;vEF+D@K>&bKLC;!DyLt|?q%1rptwE3PSAVg(Z2nkz1`aQ%KC$4#%y4CLpJGP#%S z4BNR6(|>S)s=Y=GxuKqpj6r14U^g+&aqPF2Qn;g*Y-Cyb1o~TY@&4}=SfLR7YGfHF zc|a7g4S(5N@;vesGS=po$51Ajv3!xs9HrEbwsX?V)vlWQR4on-3CZ%%9;EKIdfC~! z1$iIYiR?wB$tIlZ5cy}BJCKwY8#ibB1IrX%yr^X@Crhk>0?JyNY+kjs!zjBE*#QY)x{XAA7!o3P<8n$d{1aNNf|V r_+*6|R43FV(^R0TKvRMLNCo}{7xJfoK;VIw00000NkvXXu0mjf3!fRT literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_hw.png new file mode 100644 index 0000000000000000000000000000000000000000..82f4548431a17980827c9392ddab5ee32b0ab6ce GIT binary patch literal 3659 zcmV-R4z%%!P)Qmm5TaNO=@BZrVSxrCDByd#!~xnEu|!Yg&0dhETAA1HI?!ZN}*iG*k_H! z+;gwJ&p!82F6o`gJo7!*Tx-A9T6>?4j-EnyclQKfcV)aBNC8`b7Zfmr3>1@SxdT8N zjGu!z+Q^E@0;pfi9}71<0vC*bC8Y}FY4JH{DMzs6GOUZ12uF@bF*8^_=8*~DVor^(Ig3bbdY~=rn&zva$#xzNdjA}9j{4X{s zCKyQm3~ZQy8IT{AUsgC2YmLKf!>2pNjKKGS(_^L-1BYcPeQg~QY_IKH=7=O$fCQEu zq0B$0hj(X;0Ar2PJKcHdK{v>jU8@vuCSME6Uy{l>=;j1!^`oJ?5%hnPJx7^D3h_#8 z=v44LYR}P^dc_o|HIg@=G29z;JeN<^N*Ds>%Q?u)0?mjjF}gF-C8=?o8xm&~%Gub* zOIMpB_?SshK3=sm4tPg)w@#7O_hV$RiCW#iTq8&5CI|gKqZ?~{izl!#t}sDH-DHhzn2gdz8Vp~QL!bxgKt9j~ z&YsO0ViGZMItttwf?|y1Ku^hF;^JvDOiIwVf$^Tk(*S`lF_=E0K_3&)Ca|XlXFl1{ zlM#X65+CS1C#OZUd;s_gt*pYpL*%_)S!9!((GbiT)tiBjU9kbONhg|0mif{EW@aYb z{5cfZ*Mj|sOu0nCC|j&3=ugUEgP@B~FRRb-a9ZbsDa#4$@nAnMT}z69{UK;BDFcEW z6Sqv_9h4x@2fV#)nTgsC8Vsm20vOrr;W&}3tP|6(J}6?jDJaEWg0kgvu+NG_V;fx+ z+n5}>hV(%mFFDYwpcDJD5I&7|xkf0i@{K^3E6&|FMz9{uE3cIq)2D9!3j?Axr_jY?a_S zf`r|LLQ)Dive$%lvV;F1)7<=dQ8rSjV{uM@@6C|NEs{^vba#)Cu970)jS#fQI+{dF z3{RGw`L@wLZ+Nm?0qI%udMc;YRq{x*mKgz>oo4<`RrcGd1duqB%~t-#PWFfLAvLzA zq=zos+o4T5OYI!V>Zb?cU8@w2xzjb|%Wf&qu>+j_UY0#jT_`;FMnQKp=#`rb+GJ5K zPhLc_vp~WxWC1@X)8v2bOuKN-!F2@iay}$KO0ub)mQ(?tPZ*x;Cr+lgmkB|0#X)|6 zMh8Bgvn?J4!sa@K?P&VO-_q?7c+87lY34*(gK+20WUkmU-+~^2Gl2gBdRSd>h5}Bn z8^__^2R81E`KJU!p7Fjtl96Zwvl+V3 zTQ+yEY^RMr@kJ$DZ8d?9_rgADq_;^>)U@8_7>plKBY;D?o#)zsDvHIRrj;x#KyI>d zON&K8U8>5_{=c7<^&Eu^0djR!1k1iDdq`jjF$*Ps_%V_R$^#@3J?I*?UEijhmoa9Vt0y z79)LP89^Hf+bUxhy9N5cc8b%DIBwXW(XS$1>SoK0 zox^GhMV3uK^=VN&4;4e&PI03LH|my@ggfgJ0o{@h~^<9Tmg>6A^S=unIGs50(m~J zHR_B-F>{PgBd2rEm=Y|49}d0Au2%5e&`H5#HrzNgocD{Blv+g;#}GT*3o0TQ`AstY0dl7T)uL~;!D zWX{P5u&;Bz5;qyQY8DaCD9TW-9||{2=!P2~J%e)%z`ok}h~>`dgE_}`1O#*C#gVgc z+~+XHhP6STy?{4%vV~iWjcJ=lLT)f~+tk9>mB=U?MyDIM%o}9u7m8M^fDLb>uiif?{z}a}_1TuFOur}6s zYX%Yx&j9`mnEEgb>KyRx=W1YKTg7%hE=jPczfUST&v&-_N^za`CWKFECF4W(IOEpRz zTG~<3+9$AW2bOMmR^*+BxD&vh!U+VHZkJZH%lj{DX6Jewbg;sHnvwhTHEYeyaxG6VAbi* zBU*J-m6ES0;$#+l<->u#K*qF!R_(KP_JMt|u({4)4XNV z*9Jrs{1(CXx z3JnB>FQDqx=vywye|UL7$8Q#%27c`9k3h~24Ct%QMltIkDBrHr*8+1f=jhPJzpW9x zuf>{uAABFJZ;o$g;7;ZuJ36YqU+@KF1)^gYflmU5hfZ=j;s4b$!nH%u>libSIRMPX zoEJk}JA=`VZ%E%H?F`(7Tx3VbC?{Ld``(F5!rz4X3C|k{`Vx?z@SL*=N_hIv_sbzR z=N8)VgM2>cloxy-eBF6(BegSd{^^FolDePQi*98vf z;us7Da_Li5evAP!wl0iOtfdIv=@KMA#I!NuYh9{HJ`w@b6cp$&C$rO!Ls$5I!}&Hl zcz($I4POFuEzdZ{Fcw(#F*M9cV6Ci~wX+W%c)9ltAoFgQ{UaxP@ntA@^ris$>G@$` z6HfUMQFm-6pQDcjQFFmwX> z(u050IRmT%AHs=?_~f64QU$+J?UNz%fV2#hhipT3FNgTtfp{K(YMW=0;%ElW-gCak&M)a^PU+ z!C_1pur0PZaUhRP?b^_hp};4ASAZ$F1||Qbn;f`cqfZK$levf1F6ef2L?tsIIgn51&mN%Td|lTCtPAv=@Yx%wiXLM?Rs#9Q9uL&5tOy-6aRe|(+s(*r9~_mz d5f~hS{{zA5jrW3QAQAuo002ovPDHLkV1l(~-4p-- literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png new file mode 100644 index 0000000000000000000000000000000000000000..2678d0d752451290b34f1c8903f86998106789f4 GIT binary patch literal 2347 zcmV+`3Dow9P)2VSB@vaqi;Sd9#IpLsvJ$i+O_RjlQK^+ymgKW7OWQu* zZLgiZJHMGZ_ny1nUG@iG&z#@mJ2SsKXU@!=wW6X`S~E~g1}cjQ&LXz9wze-k!@)4n z2OI)=)nD6i-34}opTJl3SW{V9`5EPwCnTgD7!6(on?a%SGlBELIMA`#XNpb?01p6l zENj^Y;S->Lvr80>?gO3ydqJsX9~Ed+9bfi|qLH1!ec%t!)bbY<&H|mwGEp>aF!&M_ zD*q6u$7U8^GYQN)ip40{#TCvKB|p9}~eK&oL3os4kxkJC*eX8lEos0A+_*LVUY`+rXzF zR=&kiF$brpM{|-jacf(W-QEo{Z3bPk1EtP$q6A;9iZ{84B6V6#UkRdK+4xlfYY8wv zs?i}QD$p;XjJxFKP`vB}YSb)t5frFk@kb?)baSzz(_9gJo#WFJ ztOQw$_H##tejt4G16wQZCqnU2b}D!sBt_XjHx!Id4`9s$NxocpH-%lfn~1BD6dXzT zXj|fvZ77RBnS?~6;05p-(3@sLC^@p@cMtH1jy4_zBSDWGC*`i-Z15mZoj%dy=ADzU zYwxB#p-aZ)>TU8Xt$EwkB6J#oI>P7~YLtAyLqIEGOD0F~=oG*u*-X}<2Dt3BX11e6 zn()WF{CzrN#(^3KpHzCgd6xj#hsx0*Kl|z}sg1@Q3cgM>YCGi%3$2t`CCM5|xA}O9 z)8bKybjd(pY)NgjrW4TmXA(HF*vjD0u*c*2L}ImJp{O z$|d(C6QD1bnFuwV4|MjUSF^68G9mVm@O5IZ6P1zcjmOc%)*O!jw{QJ_XpOV2UFb{@e!`rkdD|ZfVEk@H6s3V zHNYV;%Y*;vA-LN?l2cXx?`fBCz9ARjxZY()x-D=_23B%(@aCQ0uvZ!J>)kaPT1eV} zAAn0zbqs=;E)sO#gQ!Oxzkc9pU?m4r?PW%H_N(!+J|;fD-zla5k#(@7&nKx~)%a_P zU_GiseeEHxH_#th?EyY{17l@?OY6AJ2FVy-Y$F>a)dtZ+jhrJCa9QU!*ID7joDOt= zACix8=w|Wc^!SW5i1f9i(OWe%v`@(q=UtcQ-N)W8GaRjY~^2wu>1(fBHI7_K%pa@s^FmXoNokuC;v7SCgDo9($ds#U+U397oUQ zg3~>nf0E=xz1CaIBSvEMhP=Q&%bhbQ+UVQ-`2EIRBn2&u7 zqvvm~#S0Z%YlpIUi_yMIz(x=wI+x0JKtNcw38HPj*LN~uIsphCprsy8ke&*5Bx_2P zvmQa(0-Tnnk@)|TXpdD~hvDQjy!pP)w-}^4pV1k!b$oCsK5198s@vK(>7(LOI7cx* znA;8!Nbu96;@jbCSFTfl8SrWKot;qmFt8mQ2vNPmV|s(%JVyidI6Vc9j^Rk{1Mv`G zJyw{SL{z`_U0%UQCzMK34bbDJKk_s;onA7JvB8k1f))6V@c1{CX(f-w88Ma7<~H~i z^0>#)H~N#6eo;}ScZzODDU+ja=C2E$EPdajYS8gSSxAFNOf6!_>J6r|llKpDb_Aoy}sNc{PxLR|58y zZD#1`97fv&m*_vRWbq?3?ntO5G|uB+|~+SE4hY_zt%H3P{E{0qoT^sKUt R{!{<}002ovPDHLkV1kauR`UP= literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin_mini.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..c4313763230cfc00fe9ef3d82b9e10cfc0ebd9d8 GIT binary patch literal 707 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9SkfJR9T^xl_H+M9WCijqQX@Rm ze0{+RIT#q*GZ|QbqKrT+1;h*tObeLcB3cWW5p0m;_e<@DKqY3LE{-7)oNuSudLMBR zXtT8s&CkpY?nxlYZ=+mbx`CU9xwP z`XAHV zEkDKe)tA~X^}e@Yzmp(+*X+(872*CZaV9No-iv2&moD0H?a)EiEsMP$aC1e-vx{Hk z5He_9A$m0NZl0&DW8<5L4=l6Fy#+SLU%3>u_gZwBpOG)ur>3aiPcKb1J|C_jD>~u( zidog`H!Z6B+G2e?`)k<#+y|^-edouHPja&wV~`bIh{6tIxOi_|nQ3`6&q(f*LcAEn9GO$q(&Jx${%J z?VGza)^zsww=F1XwDM}y`F{fPTSPZ|1 z^pTed{!1pjSSDgURfB(KIm^j)jdwYU?paK8Dt^JSc45Hup5nt9+ovp^^?bcyxzvm@ gg|`m38dzopr0GLD~(*OVf literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png index 4e05817766f3eac9f7cc0f6f5479676567a162db..6b9a52a8cd7415f33304ae1f8117f3b38ac26598 100644 GIT binary patch delta 929 zcmV;S177^62(|~1BYyw{XF*Lt006O%3;baP000ARNkl`8IifADg78YV*6)Q`zGGJw)|AK|Y+W#RIf}K@Th!)ytsf}=u7|_HYMJ!B+IX@%W z-O29T%*@@nJ9EB)FEjJz&6_tLCUd)&WMV>#5>Nt4KnW-TC4ZmN#MXBEPoh%u+kW&xz6O%t`rWq93mT^C7&}R%IO4g?z&>72I#kI zLxJNLT>hy6dVkJ_-nljvFuvmQJ?L_XX`D-SlY8SbIo&`$m-JEm?x15xD!(M7ZA%J} zNgPOKQw#Pcq&6VC*k7PJIMTF=Ewvx9$_6BZ1!qPY53!9Mpi#mxAjb-j1I|Xs$;o`j z29N`ed2)W7Z91eL3qT%lt^#GC*NWr;`M}|m?|sOrv44G&2K2At7*NRqY64EOfSQ7n zB%mhYBnPNzI0jH_?_zBB9P6J)$I&)=#;46XwOB>~XH^LNNw9^RNUl=CqZBg;_5kga zg09iOSa=mJ>|NADQu%`MY~d}p@R>w!tpF>uPs-kbRx4=U3=EOG6JS0MQf>Uevq&PJ;18ElZYR2P%V?anrh5%yzekbRv6d&7mjXf?n!vb=^G2l)i-(Tg#2WJ>S zE;!jK^n?^AoIwHk!tsO@FPuRDg~BO8T4lan%zyKd^EoGr(MoM+o3-l_VSK*}dA@F5 zW@r8sT0kGsQ#6x}MO%|(rAW!*bg$xA7@TmVm`T`*Jr*q~aYoHuA(iokV?andt^s83 zi*gxnIDvrfm*_l{K&E8#{R66gc~g8fANt4KnW-TC7=Y9fEp4|0ycp^q-ti~UrDw{00000NkvXXu0mjf DF&n0d delta 1043 zcmV+u1nm2^2d4;-BYy+#NklYtIXtpp2RLm0Gw9-X^8$Rs-6n$2Ic|d zS`_mduq4Z}}(7V7- zz-YTZuxwMT5ncd}0llGPt1`uk@-*;mJvkw&EXbS&><4Bv6Qs(5wgdAW+aDAOQdL3g zfz_V2O+^A#F@H(F4h#Z4j<$WkDl^2|249k{nxL7$kS8e**|YG`M^%uiSib^&j*xd z4(bQK_EfArfl~iSB@ut;N0&m7saU7%J+WFY*lVn-&3=eaP`BqG zQ?b7D$bY$MPZXP$6QbJ%?FD8#wwtQ+Ch$k>4zyZOpB>cq_WH>EyUoYPz<_7Zb-<4; z?t6Y3tY8x*U9PDyUrHL^KrBXSU*b|S4Kgb z1K+spFYDzTah{QM$rIzeq^Dw?pT!h3P)E)~Mt>x|6^Qe=q~o4rZ%BGRmYkS^W=Xo6 zL(W5t$WJ6?HF3=QFFePXv*(2|<-`(X^2*VTvt#>Cnb*!TU|a$*QFgFE9H z(6FTGl2%LlH!$#1k|s%7+U|-KTacL!gPs8yA#=yd3h# zX+gW?v_jAnn=f3PwU-%rJM*5TQBSNjosiS4pb1uji($JuSF}U(CH+$q@6%4n2??sV zVAf-A%=J5V8?_H~H~QphuU%w+&OWYktbf5cEy1^7=46c7t$}>8tdrk(H%ze=0XbW$ zB&U%n_7ZTy^ZyWL3G@xu-N`ajbWM7#N6tB$H!3A3giny`fq-FPF)-4Zu672WpnWyJ zk`Y_U{;H}7AE7dD^2~Bu&OfvFrYcLJGM`8!5{X12kw_#GiFg421M1h|+|N!-rwjl9 N002ovPDHLkV1jyS{@nlo diff --git a/TMessagesProj/src/main/res/drawable/buy_with_googlepay_button_content.xml b/TMessagesProj/src/main/res/drawable/buy_with_googlepay_button_content.xml new file mode 100644 index 000000000..a893cd0ca --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/buy_with_googlepay_button_content.xml @@ -0,0 +1,54 @@ + + + + + + + + + + diff --git a/TMessagesProj/src/main/res/drawable/googlepay_button_background.xml b/TMessagesProj/src/main/res/drawable/googlepay_button_background.xml new file mode 100644 index 000000000..b81005b06 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/googlepay_button_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/TMessagesProj/src/main/res/drawable/googlepay_button_content.xml b/TMessagesProj/src/main/res/drawable/googlepay_button_content.xml new file mode 100644 index 000000000..b2cdb1d52 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/googlepay_button_content.xml @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/TMessagesProj/src/main/res/drawable/googlepay_button_no_shadow_background.xml b/TMessagesProj/src/main/res/drawable/googlepay_button_no_shadow_background.xml new file mode 100644 index 000000000..9543c4bcb --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/googlepay_button_no_shadow_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/TMessagesProj/src/main/res/drawable/googlepay_button_overlay.xml b/TMessagesProj/src/main/res/drawable/googlepay_button_overlay.xml new file mode 100644 index 000000000..70c7a9227 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/googlepay_button_overlay.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/TMessagesProj/src/main/res/raw/ic_admin.json b/TMessagesProj/src/main/res/raw/ic_admin.json new file mode 100644 index 000000000..a5563ecfb --- /dev/null +++ b/TMessagesProj/src/main/res/raw/ic_admin.json @@ -0,0 +1 @@ +{"v":"5.7.1","fr":60,"ip":0,"op":120,"w":512,"h":512,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":27,"s":[0]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":37,"s":[8]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":46,"s":[-6]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":54,"s":[3]},{"t":60,"s":[0]}],"ix":10},"p":{"a":0,"k":[248,442,0],"ix":2},"a":{"a":0,"k":[50,100,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shield","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":4,"s":[-22]},{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":16,"s":[8]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":30,"s":[-15]},{"t":41,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[-70.6,6.05,0],"to":[42.6,-67.05,0],"ti":[0,0,0]},{"i":{"x":0.828,"y":0.044},"o":{"x":0.6,"y":0},"t":13,"s":[97.399,-129.949,0],"to":[-19.379,6.221,0],"ti":[0,0,0]},{"i":{"x":0.406,"y":1},"o":{"x":0.246,"y":0.374},"t":21,"s":[63.182,-110.868,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.573,"y":0.64},"o":{"x":0.369,"y":0},"t":27,"s":[-15.6,-36.95,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.566,"y":1},"o":{"x":0.251,"y":0.573},"t":33,"s":[37.19,-71.312,0],"to":[0,0,0],"ti":[0,0,0]},{"t":38,"s":[53.4,-81.95,0]}],"ix":2},"a":{"a":0,"k":[-4.6,4.05,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":7,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0.054,-0.115],[0,0],[0,0],[0.048,-0.003],[0.138,-0.008],[-0.012,-0.101],[0,0],[0,0],[0.023,-0.088],[0,0],[-0.079,0.063],[0,0],[0,0],[-0.014,-0.042],[-0.03,-0.034],[-0.017,0.128],[0,0],[0,0],[-0.043,0.054],[0,0],[0,0],[0.051,0.018],[0,0],[0,0],[-0.006,0.095],[0,0],[0,0]],"o":[[0,0],[0,0],[-0.041,0.082],[0,0],[-0.058,0.001],[0,0],[0,0],[0.006,0.049],[0,0],[-0.077,0.24],[0,0],[0,0],[0.047,-0.03],[0.008,0.024],[0.041,0.046],[0,0],[0,0],[0.023,-0.088],[0,0],[0,0],[0.092,-0.12],[0,0],[0,0],[-0.036,-0.013],[0,0],[0,0],[0.034,-0.355]],"v":[[197.681,26.778],[197.681,26.778],[196.951,28.298],[196.816,28.443],[196.076,28.316],[195.983,28.583],[195.983,28.583],[196.174,29.997],[196.152,30.23],[195.646,31.782],[195.713,32.046],[195.713,32.046],[196.449,31.536],[196.574,31.58],[196.975,32.531],[197.11,32.346],[197.11,32.346],[197.427,30.774],[197.52,30.567],[197.52,30.567],[198.395,29.528],[198.452,29.165],[198.452,29.165],[197.764,28.825],[197.71,28.662],[197.71,28.662],[197.837,26.926]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.622,"y":0},"t":13,"s":[{"i":[[1.53,-2.811],[0,0],[0,0],[1.348,-0.085],[3.904,-0.201],[-0.353,-2.474],[0,0],[0,0],[0.66,-2.165],[0,0],[-2.254,1.536],[0,0],[0,0],[-0.39,-1.035],[-0.85,-0.821],[-0.491,3.133],[0,0],[0,0],[-1.232,1.325],[0,0],[0,0],[1.454,0.443],[0,0],[0,0],[-0.17,2.315],[0,0],[0,0]],"o":[[0,0],[0,0],[-1.15,2.016],[0,0],[-1.653,0.014],[0,0],[0,0],[0.171,1.197],[0,0],[-2.172,5.865],[0,0],[0,0],[1.333,-0.739],[0.221,0.587],[1.172,1.134],[0,0],[0,0],[0.66,-2.165],[0,0],[0,0],[2.598,-2.936],[0,0],[0,0],[-1.013,-0.309],[0,0],[0,0],[0.973,-8.699]],"v":[[196.148,-38.703],[196.148,-38.703],[175.448,-1.5],[171.612,2.063],[150.62,-1.056],[147.998,5.475],[147.998,5.475],[153.407,40.102],[152.781,45.789],[138.446,83.787],[140.336,90.241],[140.336,90.241],[161.217,77.752],[164.746,78.828],[176.121,102.113],[179.957,97.588],[179.957,97.588],[188.94,59.103],[191.592,54.034],[191.592,54.034],[209.206,25.848],[210.812,16.948],[210.812,16.948],[198.515,11.41],[196.978,7.43],[196.978,7.43],[200.575,-35.063]],"c":true}]},{"i":{"x":0.472,"y":1},"o":{"x":0.167,"y":0.167},"t":21,"s":[{"i":[[1.543,-3.678],[0,0],[0,0],[2.343,-0.416],[6.806,-1.149],[-1.641,-2.84],[0,0],[0,0],[0.274,-2.712],[0,0],[-3.346,2.341],[0,0],[0,0],[-1.114,-1.132],[-1.837,-0.772],[0.423,3.815],[0,0],[0,0],[-1.628,1.853],[0,0],[0,0],[2.749,0.184],[0,0],[0,0],[0.652,2.774],[0,0],[0,0]],"o":[[0,0],[0,0],[-1.201,2.65],[0,0],[-2.912,0.402],[0,0],[0,0],[0.794,1.374],[0,0],[-1.42,7.435],[0,0],[0,0],[2.048,-1.184],[0.631,0.641],[2.535,1.065],[0,0],[0,0],[0.274,-2.712],[0,0],[0,0],[3.376,-4.075],[0,0],[0,0],[-1.915,-0.128],[0,0],[0,0],[-1.861,-10.503]],"v":[[90.227,-80.159],[90.227,-80.159],[69.004,-31.379],[63.699,-26.274],[25.372,-25.056],[23.432,-16.728],[23.432,-16.728],[47.224,22.913],[48.458,29.777],[38.795,78.01],[44.785,85.193],[44.785,85.193],[76.495,65.562],[83.166,66.009],[112.82,90.859],[117.727,84.617],[117.727,84.617],[117.745,37.059],[120.341,30.451],[120.341,30.451],[150.694,-6.515],[149.867,-17.403],[149.867,-17.403],[115.021,-21.516],[110.671,-25.858],[110.671,-25.858],[99.536,-76.893]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":27,"s":[{"i":[[1.521,-5.435],[0,0],[0,0],[3.699,-1.08],[10.762,-3.057],[-3.433,-3.587],[0,0],[0,0],[-0.284,-3.821],[0,0],[-4.813,3.967],[0,0],[0,0],[-2.116,-1.33],[-3.196,-0.676],[1.714,5.202],[0,0],[0,0],[-2.15,2.92],[0,0],[0,0],[4.521,-0.335],[0,0],[0,0],[1.807,3.708],[0,0],[0,0]],"o":[[0,0],[0,0],[-1.24,3.934],[0,0],[-4.629,1.184],[0,0],[0,0],[1.661,1.736],[0,0],[-0.31,10.62],[0,0],[0,0],[3.012,-2.083],[1.2,0.754],[4.411,0.933],[0,0],[0,0],[-0.284,-3.821],[0,0],[0,0],[4.396,-6.378],[0,0],[0,0],[-3.149,0.234],[0,0],[0,0],[-5.853,-14.17]],"v":[[4.752,-130.436],[4.752,-130.436],[-16.652,-58.204],[-23.907,-49.981],[-85.926,-40.054],[-86.843,-28.084],[-86.843,-28.084],[-37.479,21.794],[-33.626,31.051],[-36.372,100.039],[-24.696,108.716],[-24.696,108.716],[21.606,74.668],[32.578,73.854],[87.5,101.953],[93.804,92.239],[93.804,92.239],[81.042,26.26],[83.487,16.535],[83.487,16.535],[128.097,-40.316],[123.822,-55.243],[123.822,-55.243],[60.856,-54.412],[52.613,-59.502],[52.613,-59.502],[20.773,-127.907]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":33,"s":[{"i":[[1.612,-4.294],[0,0],[0,0],[3.168,-0.65],[9.21,-1.822],[-2.654,-3.1],[0,0],[0,0],[0,-3.1],[0,0],[-4.281,2.912],[0,0],[0,0],[-1.691,-1.2],[-2.637,-0.737],[1.113,4.3],[0,0],[0,0],[-1.984,2.227],[0,0],[0,0],[3.81,0],[0,0],[0,0],[1.284,3.1],[0,0],[0,0]],"o":[[0,0],[0,0],[-1.284,3.1],[0,0],[-3.953,0.678],[0,0],[0,0],[1.284,1.5],[0,0],[-0.92,8.55],[0,0],[0,0],[2.654,-1.5],[0.958,0.68],[3.638,1.017],[0,0],[0,0],[0,-3.1],[0,0],[0,0],[4.081,-4.883],[0,0],[0,0],[-2.654,0],[0,0],[0,0],[-4.024,-11.783]],"v":[[10.342,-108.269],[10.342,-108.269],[-12.088,-51.269],[-18.68,-45.069],[-71.273,-40.772],[-72.786,-31.169],[-72.786,-31.169],[-34.518,12.031],[-31.864,19.731],[-38.456,75.231],[-29.21,82.931],[-29.21,82.931],[11.712,58.231],[20.958,58.231],[65.239,84.191],[71.126,76.731],[71.126,76.731],[64.534,22.731],[67.188,15.031],[67.188,15.031],[108.109,-28.169],[105.456,-40.469],[105.456,-40.469],[52.634,-43.569],[46.042,-48.169],[46.042,-48.169],[23.612,-105.269]],"c":true}]},{"t":55,"s":[{"i":[[1.883,-4.294],[0,0],[0,0],[3.7,-0.65],[10.758,-1.822],[-3.1,-3.1],[0,0],[0,0],[0,-3.1],[0,0],[-5,2.912],[0,0],[0,0],[-1.975,-1.2],[-3.08,-0.737],[1.3,4.3],[0,0],[0,0],[-2.317,2.227],[0,0],[0,0],[4.45,0],[0,0],[0,0],[1.5,3.1],[0,0],[0,0]],"o":[[0,0],[0,0],[-1.5,3.1],[0,0],[-4.617,0.678],[0,0],[0,0],[1.5,1.5],[0,0],[-1.075,8.55],[0,0],[0,0],[3.1,-1.5],[1.119,0.68],[4.25,1.017],[0,0],[0,0],[0,-3.1],[0,0],[0,0],[4.767,-4.883],[0,0],[0,0],[-3.1,0],[0,0],[0,0],[-4.7,-11.783]],"v":[[-10.8,-102.3],[-10.8,-102.3],[-37,-45.3],[-44.7,-39.1],[-106.133,-34.803],[-107.9,-25.2],[-107.9,-25.2],[-63.2,18],[-60.1,25.7],[-67.8,81.2],[-57,88.9],[-57,88.9],[-9.2,64.2],[1.6,64.2],[53.323,90.16],[60.2,82.7],[60.2,82.7],[52.5,28.7],[55.6,21],[55.6,21],[103.4,-22.2],[100.3,-34.5],[100.3,-34.5],[38.6,-37.6],[30.9,-42.2],[30.9,-42.2],[4.7,-99.3]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-39.071,-17.523],[-0.764,-17.411],[0,0],[17.667,0],[1.869,90.758],[0,0],[0,0],[-13.024,0]],"o":[[0,0],[13.024,1.003],[0,0],[0,0],[0,92.831],[-17.667,0],[0,0],[0.935,-17.757],[41.845,-19.596],[0,0]],"v":[[-5.504,-119.714],[-3.696,-119.714],[74.447,-91.891],[97.721,-65.072],[97.721,-5.28],[-4.6,127.814],[-106.921,-2.137],[-106.921,-64.002],[-88.29,-89.818],[-5.504,-119.714]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.764,"y":0},"t":13,"s":[{"i":[[0,0],[0,0],[-19.582,-22.963],[-0.383,-22.817],[0,0],[8.854,0],[0.937,118.934],[0,0],[0,0],[-6.527,0]],"o":[[0,0],[6.527,1.315],[0,0],[0,0],[0,121.651],[-8.854,0],[0,0],[0.468,-23.27],[20.972,-25.68],[0,0]],"v":[[-5.053,-158.136],[-4.147,-158.136],[35.018,-121.676],[46.682,-86.531],[46.682,-8.176],[-4.6,166.236],[-55.882,-4.057],[-55.882,-85.128],[-46.544,-118.959],[-5.053,-158.136]],"c":true}]},{"i":{"x":0.614,"y":1},"o":{"x":0.167,"y":0.167},"t":21,"s":[{"i":[[0,0],[0,0],[-36.397,-23.702],[-0.712,-23.551],[0,0],[16.457,0],[1.741,122.762],[0,0],[0,0],[-12.132,0]],"o":[[0,0],[12.132,1.357],[0,0],[0,0],[0,125.566],[-16.457,0],[0,0],[0.871,-24.019],[38.981,-26.506],[0,0]],"v":[[-5.443,-163.357],[-3.757,-163.357],[69.037,-125.723],[90.718,-89.446],[90.718,-8.57],[-4.6,171.457],[-99.918,-4.318],[-99.918,-87.999],[-82.562,-122.919],[-5.443,-163.357]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":27,"s":[{"i":[[0,0],[0,0],[-59.948,-29.521],[-1.172,-29.333],[0,0],[27.106,0],[2.868,152.898],[0,0],[0,0],[-19.983,0]],"o":[[0,0],[19.983,1.69],[0,0],[0,0],[0,156.391],[-27.106,0],[0,0],[1.434,-29.915],[64.204,-33.013],[0,0]],"v":[[-5.988,-204.453],[-3.212,-204.453],[116.684,-157.581],[152.394,-112.398],[152.394,-11.668],[-4.6,212.553],[-161.594,-6.372],[-161.594,-110.596],[-133.008,-154.088],[-5.988,-204.453]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":33,"s":[{"i":[[0,0],[0,0],[-59.556,-26.2],[-1.164,-26.033],[0,0],[26.929,0],[2.849,135.7],[0,0],[0,0],[-19.852,0]],"o":[[0,0],[19.852,1.5],[0,0],[0,0],[0,138.8],[-26.929,0],[0,0],[1.425,-26.55],[63.784,-29.3],[0,0]],"v":[[-5.979,-181],[-3.221,-181],[115.891,-139.4],[151.368,-99.3],[151.368,-9.9],[-4.6,189.1],[-160.568,-5.2],[-160.568,-97.7],[-132.168,-136.3],[-5.979,-181]],"c":true}]},{"t":55,"s":[{"i":[[0,0],[0,0],[-64.8,-26.2],[-1.267,-26.033],[0,0],[29.3,0],[3.1,135.7],[0,0],[0,0],[-21.6,0]],"o":[[0,0],[21.6,1.5],[0,0],[0,0],[0,138.8],[-29.3,0],[0,0],[1.55,-26.55],[69.4,-29.3],[0,0]],"v":[[-6.1,-181],[-3.1,-181],[126.5,-139.4],[165.1,-99.3],[165.1,-9.9],[-4.6,189.1],[-174.3,-5.2],[-174.3,-97.7],[-143.4,-136.3],[-6.1,-181]],"c":true}]}],"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1.854,0.749],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"User-promoted","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/ic_pin.json b/TMessagesProj/src/main/res/raw/ic_pin.json new file mode 100644 index 000000000..fcf564862 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/ic_pin.json @@ -0,0 +1 @@ +{"v":"5.7.1","fr":60,"ip":0,"op":120,"w":512,"h":512,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 2","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":32,"s":[290,268,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":35,"s":[290,306,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":40,"s":[290,258,0],"to":[0,0,0],"ti":[0,0,0]},{"t":45,"s":[290,268,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"Null 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":30,"s":[0]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":35,"s":[-6]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":40,"s":[3]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":46,"s":[-2]},{"t":51,"s":[0]}],"ix":10},"p":{"a":0,"k":[-22,225.242,0],"ix":2},"a":{"a":0,"k":[50,100,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Pin","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[-70]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":21,"s":[20]},{"t":33,"s":[-25]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[-84.078,136.681,0],"to":[62.078,-209.923,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":0.97},"o":{"x":0.8,"y":0},"t":23,"s":[229.922,-217.319,0],"to":[-73.499,6.818,0],"ti":[0,0,0]},{"i":{"x":0.454,"y":1},"o":{"x":0.3,"y":0.477},"t":35,"s":[121.14,-79.244,0],"to":[0,0,0],"ti":[0,0,0]},{"t":52,"s":[117.922,-63.319,0]}],"ix":2},"a":{"a":0,"k":[-0.078,-0.077,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":11,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[20.022,-13.297],[3.194,3.194],[-5.784,10.02],[-47.616,53.695],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-42.204,37.036],[-14.847,9.861],[-2.434,-2.434],[12.035,-20.85],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-136.654,154.899],[-163.6,164.9],[-158.576,146.218],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.8,"y":0},"t":23,"s":[{"i":[[22.651,7.683],[0,0],[0,0],[8.244,-1.288],[2.539,2.539],[-0.403,4.264],[-9.355,10.145],[11.638,48.666],[-8.869,7.791],[-16.198,1.588],[-18.505,-9.809],[0,0],[-21.239,-19.396],[0,0],[15.503,-15.503],[8.018,-6.936],[1.858,-23.456],[12.128,-2.613]],"o":[[-43.538,-14.768],[0,0],[-5.882,7.456],[-6.114,0.956],[-1.935,-1.935],[0.838,-8.872],[0,0],[-5.116,-21.393],[6.784,-5.96],[15.427,-1.512],[4.338,-3.765],[15.503,-15.503],[0,0],[18.864,18.607],[0,0],[8.813,11.486],[-1.601,20.216],[-4.575,0.762]],"v":[[2.874,119.855],[-61.837,85.113],[-64.246,85.636],[-87.981,98.807],[-101.997,96.454],[-104.236,86.825],[-88.404,55.325],[-126.708,-15.522],[-113.061,-64.163],[-75.927,-78.896],[-21.024,-66.322],[-9.116,-76.07],[61.482,-76.815],[74.583,-63.075],[76.88,6.603],[68.085,16.549],[82.382,76.958],[46.874,120.336]],"c":true}]},{"i":{"x":0.7,"y":1},"o":{"x":0.167,"y":0.167},"t":33,"s":[{"i":[[7.201,4.974],[0,0],[0,0],[18.27,-11.51],[1.583,2.769],[-4.983,9.164],[-41.923,47.215],[1.732,7.241],[-10.257,10.097],[-7.517,0.236],[-2.753,-1.459],[0,0],[-19.759,-19.485],[0,0],[18.905,-18.905],[1.193,-1.032],[0.276,-3.49],[13.58,-1.524]],"o":[[-6.478,-2.197],[0,0],[-36.799,32.634],[-13.548,8.536],[-1.657,-2.898],[10.369,-19.068],[0,0],[-9.699,-12.121],[4.84,-4.717],[2.296,-0.225],[0.645,-0.56],[18.905,-18.905],[0,0],[19.405,19.367],[0,0],[1.311,1.709],[-0.238,14.499],[-5.579,0.93]],"v":[[38.647,144.153],[-37.376,72.589],[-46.672,80.328],[-129.955,145.978],[-154.434,154.716],[-149.609,137.853],[-71.972,37.514],[-142.789,-39.422],[-140.758,-77.303],[-121.188,-85.879],[-17.258,-86.562],[35.586,-140.361],[106.1,-140.472],[138.693,-107.785],[139.035,-37.407],[86.654,16.422],[86.228,121.171],[59.466,148.849]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":35,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[20.022,-13.297],[3.194,3.193],[5.66,3.934],[-47.616,53.695],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-42.204,37.036],[-4.178,-2.678],[-2.434,-2.434],[12.035,-20.85],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[47.23,154.364],[-33.1,70.4],[-43.6,79.4],[-136.654,154.899],[-149.486,149.954],[-157.451,144.269],[-69.1,34.4],[-147.796,-51.796],[-147.796,-87.796],[-131.296,-95.296],[-25.332,-78.976],[25.668,-124.887],[96.168,-124.887],[129.57,-90.387],[129.57,-19.887],[78.57,26.024],[89.23,134.864],[63.997,159.797]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0.167},"t":40,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[19.56,-13.406],[4.136,3.243],[3.389,4.721],[-44.499,50.18],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-39.159,34.364],[-5.104,-1.789],[-3.007,-2.41],[12.781,-20.901],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-131.435,151.054],[-145.43,146.031],[-154.111,139.447],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]},{"t":52,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[17.61,-13.865],[8.109,3.45],[-6.186,8.042],[-31.36,35.363],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-26.322,23.099],[-9.008,1.959],[-5.419,-2.305],[15.926,-21.117],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-109.429,134.845],[-128.33,129.488],[-140.029,119.12],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Pin-and-unpin","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Line","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":23,"s":[-25.408,280.081,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35,"s":[-25.408,240.081,0]}],"ix":2},"a":{"a":0,"k":[-41.408,189.581,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-130.899,189.147],[77.583,189.295]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":20,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-42.372,184.791],"ix":2},"a":{"a":0,"k":[-42.372,184.791],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.7],"y":[0.943]},"o":{"x":[0.8],"y":[0]},"t":24,"s":[50]},{"t":35,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.7],"y":[0.943]},"o":{"x":[0.8],"y":[0]},"t":24,"s":[50]},{"t":35,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":24,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/ic_unpin.json b/TMessagesProj/src/main/res/raw/ic_unpin.json new file mode 100644 index 000000000..b83a4b89d --- /dev/null +++ b/TMessagesProj/src/main/res/raw/ic_unpin.json @@ -0,0 +1 @@ +{"v":"5.7.1","fr":60,"ip":0,"op":120,"w":512,"h":512,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 3","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.423,"y":1},"o":{"x":0.312,"y":0},"t":0,"s":[236.014,476.705,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.71,"y":1},"o":{"x":0.7,"y":0},"t":29,"s":[236.014,456.705,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":1},"o":{"x":0.29,"y":0},"t":37,"s":[236.014,491.705,0],"to":[0,0,0],"ti":[0,0,0]},{"t":48,"s":[236.014,441.705,0]}],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"i":{"x":[0.71,0.71,0.71],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":8,"s":[102,98,100]},{"i":{"x":[0.71,0.71,0.71],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":17,"s":[98,102,100]},{"i":{"x":[0.71,0.71,0.71],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":26,"s":[102,98,100]},{"i":{"x":[0.71,0.71,0.71],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":37,"s":[95,95,100]},{"i":{"x":[0.71,0.71,0.71],"y":[1,1,1]},"o":{"x":[0.29,0.29,0.29],"y":[0,0,0]},"t":44,"s":[95,95,100]},{"t":54,"s":[100,100,100]}],"ix":6}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"Null 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":0,"s":[-6]},{"i":{"x":[0.499],"y":[1]},"o":{"x":[0.607],"y":[0]},"t":8,"s":[12]},{"i":{"x":[0.372],"y":[1]},"o":{"x":[0.435],"y":[0]},"t":17,"s":[-28]},{"i":{"x":[0.672],"y":[1]},"o":{"x":[0.658],"y":[0]},"t":26,"s":[0]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":37,"s":[-24]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":43,"s":[-24]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":50,"s":[-18]},{"t":56,"s":[-24]}],"ix":10},"p":{"a":0,"k":[31.986,32.537,0],"ix":2},"a":{"a":0,"k":[50,100,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Pin","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.346],"y":[0.786]},"o":{"x":[0.475],"y":[0]},"t":37,"s":[-25]},{"i":{"x":[0.599],"y":[1]},"o":{"x":[0.271],"y":[4.632]},"t":49,"s":[100]},{"t":54,"s":[100]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.797,"y":1},"o":{"x":0.261,"y":0},"t":0,"s":[113.922,-7.319,0],"to":[0,0,0],"ti":[-11.386,5.411,0]},{"i":{"x":0.684,"y":0.826},"o":{"x":0.621,"y":0},"t":37,"s":[128.497,-87.071,0],"to":[28.22,-63.562,0],"ti":[-19.046,-29.394,0]},{"i":{"x":0.506,"y":1},"o":{"x":0.203,"y":0.126},"t":44,"s":[241.015,-156.809,0],"to":[24.476,41.2,0],"ti":[52.022,-36.485,0]},{"i":{"x":0.658,"y":1},"o":{"x":0.167,"y":0},"t":54,"s":[186.712,13.283,0],"to":[0,0,0],"ti":[0,0,0]},{"t":60,"s":[205.024,-19.461,0]}],"ix":2},"a":{"a":0,"k":[-0.078,-0.077,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.71,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[10.773,-10.884],[8.109,3.45],[-6.186,8.042],[-31.36,35.363],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-26.322,23.099],[-9.008,1.959],[-5.419,-2.305],[15.926,-21.117],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-77.509,107.801],[-100.538,95.232],[-113.026,84.443],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]},{"i":{"x":0.71,"y":1},"o":{"x":0.29,"y":0},"t":8,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[5.616,-2.364],[6.24,3.352],[7.542,0.896],[-37.54,42.332],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-32.359,28.397],[-9.881,-4.145],[-4.284,-2.354],[14.447,-21.016],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-77.318,105.283],[-99.386,97.823],[-119.175,93.831],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]},{"i":{"x":0.71,"y":1},"o":{"x":0.29,"y":0},"t":17,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[18.096,-12.795],[4.217,3.247],[4.112,2.94],[-32.808,36.823],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-23.542,22.483],[-4.517,-2.286],[-3.056,-2.408],[12.845,-20.906],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[29.686,162.42],[-48.314,84.42],[-58.814,93.42],[-114.674,137.321],[-124.717,127.658],[-134.131,114.062],[-84.314,48.42],[-160.814,-29.58],[-160.814,-65.58],[-144.314,-73.08],[-31.814,-76.08],[28.186,-137.58],[98.686,-137.58],[134.686,-101.58],[134.686,-31.08],[74.686,30.42],[71.686,142.92],[46.452,167.854]],"c":true}]},{"i":{"x":0.672,"y":1},"o":{"x":0.681,"y":0},"t":26,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[19.633,-13.196],[3.4,3.204],[8.232,1.439],[-46.932,52.923],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-41.535,36.449],[-5.457,-5.479],[-2.56,-2.429],[12.198,-20.862],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-129.479,149.035],[-141.08,141.314],[-151.023,137.074],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]},{"i":{"x":0.44,"y":0.732},"o":{"x":0.167,"y":0},"t":37,"s":[{"i":[[12.742,4.584],[25.704,33.529],[0,0],[20.022,-13.297],[3.194,3.193],[-5.784,10.02],[-6.788,5.981],[4.727,15.642],[-10.5,10.5],[-15.2,1.449],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[2.285,-25.872],[13.833,-1.333]],"o":[[-12.742,-4.584],[-1.367,-0.821],[-42.204,37.036],[-14.847,9.861],[-2.434,-2.434],[12.035,-20.85],[-32.321,-29.008],[-2.571,-8.509],[4.5,-4.5],[24.837,-2.368],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[-1.678,18.999],[-5.755,0.959]],"v":[[28.513,148],[-52.461,93.855],[-55.258,94.067],[-136.654,154.899],[-158.194,158.544],[-158.576,146.217],[-97.266,47.726],[-149.832,-36.435],[-145.6,-79.6],[-119.325,-93.505],[-36.913,-73.837],[13.868,-124.603],[84.368,-124.603],[120.368,-88.603],[120.368,-18.103],[70.278,33.458],[92.928,117.383],[59.543,152.192]],"c":true}]},{"i":{"x":0.216,"y":1},"o":{"x":0.29,"y":0.139},"t":44,"s":[{"i":[[22.651,7.683],[0,0],[0,0],[8.244,-1.288],[2.539,2.539],[-0.403,4.264],[-9.355,10.145],[11.638,48.666],[-8.869,7.791],[-16.198,1.588],[-18.505,-9.809],[0,0],[-21.239,-19.396],[0,0],[15.503,-15.503],[8.018,-6.936],[1.858,-23.456],[12.128,-2.613]],"o":[[-43.538,-14.768],[0,0],[-5.882,7.456],[-6.114,0.956],[-1.935,-1.935],[0.838,-8.872],[0,0],[-5.116,-21.393],[6.784,-5.96],[15.427,-1.512],[4.338,-3.765],[15.503,-15.503],[0,0],[18.864,18.607],[0,0],[8.813,11.486],[-1.601,20.216],[-4.575,0.762]],"v":[[2.874,119.855],[-61.837,85.113],[-64.246,85.636],[-87.981,98.807],[-101.997,96.454],[-104.236,86.825],[-88.404,55.325],[-126.708,-15.522],[-113.061,-64.163],[-75.927,-78.896],[-21.024,-66.322],[-9.116,-76.07],[61.482,-76.815],[74.583,-63.075],[76.88,6.603],[68.085,16.549],[82.382,76.958],[46.874,120.336]],"c":true}]},{"t":54,"s":[{"i":[[4.5,4.5],[0,0],[0,0],[20.022,-13.297],[3.194,3.194],[-5.784,10.02],[-47.616,53.695],[0,0],[-10.5,10.5],[-6,0],[0,0],[0,0],[-19.5,-19.5],[0,0],[19.5,-19.5],[0,0],[0,0],[13.833,-1.333]],"o":[[0,0],[0,0],[-42.204,37.036],[-14.847,9.861],[-2.434,-2.434],[12.035,-20.85],[0,0],[-10.5,-10.5],[4.5,-4.5],[0,0],[0,0],[19.5,-19.5],[0,0],[19.5,19.5],[0,0],[0,0],[0,13.5],[-5.755,0.959]],"v":[[44.9,148.4],[-33.1,70.4],[-43.6,79.4],[-136.654,154.899],[-163.6,164.9],[-158.576,146.218],[-69.1,34.4],[-145.6,-43.6],[-145.6,-79.6],[-129.1,-87.1],[-16.6,-90.1],[43.4,-151.6],[113.9,-151.6],[149.9,-115.6],[149.9,-45.1],[89.9,16.4],[86.9,128.9],[61.667,153.833]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Pin-and-unpin","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Line","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[28.578,47.376,0],"ix":2},"a":{"a":0,"k":[-41.408,189.581,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-130.899,189.147],[77.583,189.295]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":20,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-42.372,184.791],"ix":2},"a":{"a":0,"k":[-42.372,184.791],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.663],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.682],"y":[0]},"t":28,"s":[85]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":37,"s":[75]},{"t":42,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.663],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.682],"y":[0]},"t":28,"s":[15]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":37,"s":[25]},{"t":42,"s":[50]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":42,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/permission_map.svg b/TMessagesProj/src/main/res/raw/permission_map.svg new file mode 100644 index 000000000..a6746e3bf --- /dev/null +++ b/TMessagesProj/src/main/res/raw/permission_map.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/permission_map_dark.svg b/TMessagesProj/src/main/res/raw/permission_map_dark.svg new file mode 100644 index 000000000..75260ca3c --- /dev/null +++ b/TMessagesProj/src/main/res/raw/permission_map_dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/permission_pin.svg b/TMessagesProj/src/main/res/raw/permission_pin.svg new file mode 100644 index 000000000..615e89f44 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/permission_pin.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/permission_pin_dark.svg b/TMessagesProj/src/main/res/raw/permission_pin_dark.svg new file mode 100644 index 000000000..e0e0f97f8 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/permission_pin_dark.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/player_prev.json b/TMessagesProj/src/main/res/raw/player_prev.json new file mode 100644 index 000000000..50890ec88 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/player_prev.json @@ -0,0 +1 @@ +{"v":"5.7.1","fr":60,"ip":0,"op":25,"w":28,"h":28,"nm":"Previous track lottie","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Triangle 4","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":9,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.73,"y":1},"o":{"x":0.567,"y":0},"t":4,"s":[25.88273333333333,14.04106666666667,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.57,"y":1},"o":{"x":0.206,"y":0},"t":15,"s":[16.0244,14.04106666666667,0],"to":[0,0,0],"ti":[0,0,0]},{"t":27,"s":[17.4244,14.04106666666667,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.73,0.73,0.667],"y":[1,1,1]},"o":{"x":[0.56,0.56,0.333],"y":[0,0,0]},"t":4,"s":[12.133333333333333,12.133333333333333,100]},{"i":{"x":[0.614,0.614,0.833],"y":[1,1,1]},"o":{"x":[0.2,0.2,0.167],"y":[0,0,0]},"t":15,"s":[49.46666666666667,49.46666666666667,100]},{"t":25,"s":[46.666666666666664,46.666666666666664,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.47,-0.33],[0,0],[-1.59,2.26],[0,1.03],[0,0],[2.77,0],[0.85,-0.59],[0,0],[-1.59,-2.26]],"o":[[0,0],[2.26,1.59],[0.59,-0.84],[0,0],[0,-2.76],[-1.03,0],[0,0],[-2.26,1.59],[0.33,0.47]],"v":[[-15.542,4.083],[9.778,21.943],[16.748,20.733],[17.658,17.853],[17.658,-17.857],[12.658,-22.857],[9.778,-21.947],[-15.542,-4.087],[-16.752,2.883]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Triangle","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":27,"st":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Triangle 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.567,"y":0},"t":0,"s":[17.4244,14.04106666666667,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[2.5494,14.04106666666667,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.766,0.766,0.667],"y":[1,1,1]},"o":{"x":[0.56,0.56,0.333],"y":[0,0,0]},"t":0,"s":[46.666666666666664,46.666666666666664,100]},{"t":15,"s":[18.666666666666668,18.666666666666668,100]}],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.73,"y":1},"o":{"x":0.56,"y":0},"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[17.659,-24.824],[-25.588,-24.826],[-25.588,25.095],[17.659,25.097]],"c":true}]},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[18.753,-24.784],[-1.119,-24.66],[-1.119,25.261],[18.753,25.137]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.47,-0.33],[0,0],[-1.59,2.26],[0,1.03],[0,0],[2.77,0],[0.85,-0.59],[0,0],[-1.59,-2.26]],"o":[[0,0],[2.26,1.59],[0.59,-0.84],[0,0],[0,-2.76],[-1.03,0],[0,0],[-2.26,1.59],[0.33,0.47]],"v":[[-15.542,4.083],[9.778,21.943],[16.748,20.733],[17.658,17.853],[17.658,-17.857],[12.658,-22.857],[9.778,-21.947],[-15.542,-4.087],[-16.752,2.883]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Triangle","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":27,"st":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Rectangle 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[4.199999999999999,13.999999999999998,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[46.666666666666664,46.666666666666664,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.21,0],[0,-2.21],[0,-6.75],[0,-2.23],[2.21,0],[0,2.23],[0,6.97],[0,2.21]],"o":[[2.21,0],[0,2.21],[0,7.25],[0,2.23],[-2.21,0],[0,-2.23],[0,-7.03],[0,-2.21]],"v":[[0,-25],[4,-21],[4,0.09],[4,21],[0,25],[-4,21],[-4,0.09],[-4,-21]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":27,"st":1,"bm":0}],"markers":[]} \ 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 c171d42c2..f543f19d9 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -249,6 +249,8 @@ Voice from all your chats will be shown here. Media from all your chats will be shown here. Chats + Message pinned + Message unpinned Promote to admin Edit admin rights @@ -564,6 +566,7 @@ Slow Mode is enabled. You can\'t send more than one message at once. Slow Mode is enabled. You can\'t select more items. Sorry, this text is too long to send as one message.\n\nSlow Mode is enabled. You can\'t send more than one message at once. + **%1$s** promoted to admin New Poll New Quiz @@ -896,10 +899,12 @@ Tap here to access saved GIFs Pin Notify all members + Also pin for %1$s Unpin Pin message Unpin message - Do you want to pin this message in this group? + Do you want to pin an older message while leaving a more recent one pinned? + Do you want to pin this message for all members in the group? Do you want to pin this message in this channel? Do you want to pin this message at the top of the chat? Do you want to unpin this message? @@ -924,6 +929,7 @@ Other Description Pinned Message + Previous Message Pinned poll edited Edit Message @@ -997,7 +1003,7 @@ Tap for photo, hold for video Tap to view as a list. Send without sound - Send Now> + Send Now Reschedule Today Schedule @@ -1043,7 +1049,6 @@ h w to private messages and groups - Shares Transfer Bot Ownership This will transfer the **full owner** rights for the bot to the selected user. Change Owner @@ -1061,6 +1066,10 @@ Choose date This chat helps you keep track of replies to your comments in Channels. Sorry, this post has been removed from the discussion group. + UNPIN ALL MESSAGES + HIDE PINNED MESSAGES + Pinned messages hidden + You will see the bar with pinned messages only if a new message is pinned. %1$s set the self-destruct timer to %2$s You set the self-destruct timer to %1$s @@ -1176,6 +1185,25 @@ %1$s pinned a live location %1$s pinned a GIF %1$s pinned an audio file + %1$s pinned \"%2$s\" + %1$s pinned a message + %1$s pinned a poll %2$s + %1$s pinned a quiz %2$s + %1$s pinned a photo + %1$s pinned a game + %1$s pinned a game score + %1$s pinned a video + %1$s pinned a file + %1$s pinned an invoice + %1$s pinned a sticker + %1$s pinned a %2$s sticker + %1$s pinned a voice message + %1$s pinned a video message + %1$s pinned a contact %2$s + %1$s pinned a map + %1$s pinned a live location + %1$s pinned a GIF + %1$s pinned an audio file Telegram Select Contact @@ -2314,6 +2342,12 @@ %1$s km away %1$s ft away %1$s mi away + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km %1$s m from you %1$s km from you %1$s ft from you @@ -2347,6 +2381,8 @@ updated just now You and %1$s %1$s sharing with %2$s + %1$s sharing with %2$s + %1$s sharing with %2$s STOP ALL You are sharing your Live Location with %1$s Choose for how long %1$s will see your accurate location. @@ -2375,6 +2411,15 @@ Set this location People will be able to find your group in the \"People Nearby\" section. Places in this area + Proximity alert + Notify when %1$s is within %2$s + Notify when someone is within %1$s + You are already closer than %1$s + Share Location + Share + For the alert to work, please share your live location in this chat. + Alert when %1$s is close + Alert when other members of the group are close Show as list Show as grid @@ -2482,6 +2527,41 @@ This is the main group video now. Photo saved to gallery Video saved to gallery + Photo saved to downloads + Video saved to downloads + GIF saved to downloads + File saved to music + File saved to downloads + %1$d files saved to downloads + File saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d photos saved to gallery + Photo saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d videos saved to gallery + Video saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d files saved to music + File saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d items saved to gallery + An item saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery Two-Step Verification Two-Step Verification @@ -2765,6 +2845,9 @@ un1 returned to the group un1 joined the group You returned to the group + un1 is now within %1$s from you + You are now within %1$s from un1 + un1 is now within %1$s from un2 You allowed this bot to message you when you logged in on %1$s. %1$s received the following documents: %2$s Personal details @@ -2941,6 +3024,7 @@ Telegram needs access to draw above other apps to play videos in Picture-in-Picture mode. SETTINGS Please allow Telegram to be shown on the lock screen so that calls can work properly. + To share your live location in this chat, Telegram needs access to your location all the time, including while the app is in the background.\n\nWe will access your location only for the duration you choose, and you can stop sharing it any time. We won\'t use your location for any purpose other than sharing it in this chat. Growth Followers @@ -3014,6 +3098,15 @@ Top days of week View Messages Open Profile + Today + Yesterday + Views + Public Shares + Private Shares + View Stats + View Channel Stats + Message Statistic + Open Message Telegram Fast @@ -3248,6 +3341,12 @@ %1$d new messages %1$d new messages %1$d new messages + %1$d messages unpinned + Message unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned %1$d messages %1$d message %1$d messages @@ -3404,6 +3503,12 @@ %1$s shares %1$s shares %1$s shares + %1$s public shares + %1$s public share + %1$s public shares + %1$s public shares + %1$s public shares + %1$s public shares %1$s shared %1$s shared %1$s shared @@ -3621,6 +3726,18 @@ %1$d comments %1$d comments %1$d comments + comments + comment + comments + comments + comments + comments + %1$d Pinned Messages + Pinned Message + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages Group Channel @@ -3694,6 +3811,7 @@ Title Heading My location + Notify when in range Video quality Aspect ratio Take one more picture @@ -3747,6 +3865,7 @@ Switched to rear camera Camera is on Camera is off + Pinned messages list MMM yyyy MMM dd yyyy, h:mm a @@ -3775,6 +3894,4 @@ \'Remind today at\' HH:mm \'Remind on\' MMM d \'at\' HH:mm \'Remind on\' MMM d yyyy \'at\' HH:mm - Today - Yesterday diff --git a/build.gradle b/build.gradle index 45d977173..9fe22834c 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'com.google.gms:google-services:4.3.3' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.google.gms:google-services:4.3.4' } } repositories { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9e14e7adc..f3dc29415 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 05 18:00:46 MSK 2020 +#Mon Oct 19 01:57:36 MSK 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip From 002c01ecd37cd08ed07b3ed84d79318d091dfc85 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 30 Oct 2020 15:41:45 +0300 Subject: [PATCH 2/2] Update to 7.2.0 (2134) --- TMessagesProj/build.gradle | 2 +- .../telegram/messenger/AndroidUtilities.java | 2 +- .../org/telegram/messenger/BuildVars.java | 2 +- .../messenger/LocationController.java | 16 +- .../telegram/messenger/MessagesStorage.java | 16 +- .../messenger/SendMessagesHelper.java | 6 +- .../telegram/messenger/browser/Browser.java | 20 +- .../ui/ActionBar/ActionBarLayout.java | 9 +- .../ui/ActionBar/ActionBarMenuItem.java | 4 +- .../java/org/telegram/ui/ActionBar/Theme.java | 4 +- .../ui/Adapters/DialogsSearchAdapter.java | 2 + .../ui/Adapters/LocationActivityAdapter.java | 2 +- .../telegram/ui/Adapters/SearchAdapter.java | 5 +- .../telegram/ui/Cells/ChatMessageCell.java | 16 +- .../java/org/telegram/ui/ChatActivity.java | 119 +++++-- .../org/telegram/ui/Components/Bulletin.java | 1 - .../ui/Components/ChatActivityEnterView.java | 56 +++- .../ui/Components/ProximitySheet.java | 5 +- .../ui/Components/RLottieImageView.java | 4 + .../RecyclerAnimationScrollHelper.java | 4 +- .../org/telegram/ui/Components/UndoView.java | 61 +++- .../org/telegram/ui/FilteredSearchView.java | 16 +- .../org/telegram/ui/LocationActivity.java | 113 ++++++- .../java/org/telegram/ui/ProfileActivity.java | 99 +++--- .../res/drawable-hdpi/msg_location_alert2.png | Bin 0 -> 730 bytes .../res/drawable-mdpi/msg_location_alert2.png | Bin 0 -> 568 bytes .../drawable-xhdpi/msg_location_alert2.png | Bin 0 -> 948 bytes .../drawable-xxhdpi/msg_location_alert2.png | Bin 0 -> 1309 bytes .../src/main/res/values-ar/strings.xml | 302 ++++++++++++----- .../src/main/res/values-de/strings.xml | 160 ++++++++- .../src/main/res/values-es/strings.xml | 166 ++++++++- .../src/main/res/values-it/strings.xml | 238 ++++++++++--- .../src/main/res/values-ko/strings.xml | 316 +++++++++++++----- .../src/main/res/values-nl/strings.xml | 144 +++++++- .../src/main/res/values-pt-rBR/strings.xml | 162 ++++++++- TMessagesProj/src/main/res/values/strings.xml | 4 + 36 files changed, 1638 insertions(+), 438 deletions(-) create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert2.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert2.png diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index a61a1f914..476392910 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -285,7 +285,7 @@ android { } } - defaultConfig.versionCode = 2128 + defaultConfig.versionCode = 2134 applicationVariants.all { variant -> variant.outputs.all { output -> diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index b6b20485e..a644bb5eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -377,7 +377,7 @@ public class AndroidUtilities { LinkSpec spec = new LinkSpec(); String url = makeUrl(m.group(0), schemes, m); - if (internalOnly && !Browser.isInternalUrl(url, null)) { + if (internalOnly && !Browser.isInternalUrl(url, true, null)) { continue; } spec.url = url; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index f3b443a44..7d2cd8109 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -18,7 +18,7 @@ public class BuildVars { public static boolean LOGS_ENABLED = false; public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; - public static int BUILD_VERSION = 2129; + public static int BUILD_VERSION = 2134; public static String BUILD_VERSION_STRING = "7.2.0"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java index a93151796..ea2444026 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java @@ -583,17 +583,17 @@ public class LocationController extends BaseController implements NotificationCe return cachedNearbyChats; } - protected void addSharingLocation(long did, int mid, int period, int radius, TLRPC.Message message) { + protected void addSharingLocation(TLRPC.Message message) { final SharingLocationInfo info = new SharingLocationInfo(); - info.did = did; - info.mid = mid; - info.period = period; - info.lastSentProximityMeters = info.proximityMeters = radius; + info.did = message.dialog_id; + info.mid = message.id; + info.period = message.media.period; + info.lastSentProximityMeters = info.proximityMeters = message.media.proximity_notification_radius; info.account = currentAccount; info.messageObject = new MessageObject(currentAccount, message, false, false); - info.stopTime = getConnectionsManager().getCurrentTime() + period; - final SharingLocationInfo old = sharingLocationsMap.get(did); - sharingLocationsMap.put(did, info); + info.stopTime = getConnectionsManager().getCurrentTime() + info.period; + final SharingLocationInfo old = sharingLocationsMap.get(info.did); + sharingLocationsMap.put(info.did, info); if (old != null) { sharingLocations.remove(old); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 23806535e..743b9cac3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -892,13 +892,13 @@ public class MessagesStorage extends BaseController { version = 68; } if (version == 68) { - database.executeFast("ALTER TABLE messages ADD COLUMN forwards INTEGER default 0").stepThis().dispose(); + executeNoException("ALTER TABLE messages ADD COLUMN forwards INTEGER default 0"); database.executeFast("PRAGMA user_version = 69").stepThis().dispose(); version = 69; } if (version == 69) { - database.executeFast("ALTER TABLE messages ADD COLUMN replies_data BLOB default NULL").stepThis().dispose(); - database.executeFast("ALTER TABLE messages ADD COLUMN thread_reply_id INTEGER default 0").stepThis().dispose(); + executeNoException("ALTER TABLE messages ADD COLUMN replies_data BLOB default NULL"); + executeNoException("ALTER TABLE messages ADD COLUMN thread_reply_id INTEGER default 0"); database.executeFast("CREATE INDEX IF NOT EXISTS uid_thread_reply_id_mid_idx_messages ON messages(uid, thread_reply_id, mid) WHERE thread_reply_id != 0;").stepThis().dispose(); database.executeFast("PRAGMA user_version = 70").stepThis().dispose(); version = 70; @@ -909,7 +909,7 @@ public class MessagesStorage extends BaseController { version = 71; } if (version == 71) { - database.executeFast("ALTER TABLE sharing_locations ADD COLUMN proximity INTEGER default 0").stepThis().dispose(); + executeNoException("ALTER TABLE sharing_locations ADD COLUMN proximity INTEGER default 0"); database.executeFast("PRAGMA user_version = 72").stepThis().dispose(); version = 72; } @@ -927,6 +927,14 @@ public class MessagesStorage extends BaseController { }); } + private void executeNoException(String query) { + try { + database.executeFast(query).stepThis().dispose(); + } catch (Exception e) { + FileLog.e(e); + } + } + private void cleanupInternal(boolean deleteFiles) { lastDateValue = 0; lastSeqValue = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 487efcb85..104a9a860 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -4846,7 +4846,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } if (MessageObject.isLiveLocationMessage(newMsgObj) && newMsgObj.via_bot_id == 0 && TextUtils.isEmpty(newMsgObj.via_bot_name)) { - getLocationController().addSharingLocation(newMsgObj.dialog_id, newMsgObj.id, newMsgObj.media.period, newMsgObj.media.proximity_notification_radius, newMsgObj); + getLocationController().addSharingLocation(newMsgObj); } if (!isSentError) { @@ -4923,7 +4923,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe TLRPC.PhotoSize strippedOld = null; TLRPC.PhotoSize strippedNew = null; TLObject photoObject = null; - if (newMsgObj.isDice()) { + if (newMsgObj.isLiveLocation() && sentMessage.media instanceof TLRPC.TL_messageMediaGeoLive) { + newMsg.media.period = sentMessage.media.period; + } else if (newMsgObj.isDice()) { TLRPC.TL_messageMediaDice mediaDice = (TLRPC.TL_messageMediaDice) newMsg.media; TLRPC.TL_messageMediaDice mediaDiceNew = (TLRPC.TL_messageMediaDice) sentMessage.media; mediaDice.value = mediaDiceNew.value; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java index ce070ef68..59e842d97 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -322,7 +322,11 @@ public class Browser { } public static boolean isInternalUrl(String url, boolean[] forceBrowser) { - return isInternalUri(Uri.parse(url), forceBrowser); + return isInternalUri(Uri.parse(url), false, forceBrowser); + } + + public static boolean isInternalUrl(String url, boolean all, boolean[] forceBrowser) { + return isInternalUri(Uri.parse(url), all, forceBrowser); } public static boolean isPassportUrl(String url) { @@ -341,6 +345,10 @@ public class Browser { } public static boolean isInternalUri(Uri uri, boolean[] forceBrowser) { + return isInternalUri(uri, false, forceBrowser); + } + + public static boolean isInternalUri(Uri uri, boolean all, boolean[] forceBrowser) { String host = uri.getHost(); host = host != null ? host.toLowerCase() : ""; if ("ton".equals(uri.getScheme())) { @@ -359,6 +367,9 @@ public class Browser { } else if ("telegram.dog".equals(host)) { String path = uri.getPath(); if (path != null && path.length() > 1) { + if (all) { + return true; + } path = path.substring(1).toLowerCase(); if (path.startsWith("blog") || path.equals("iv") || path.startsWith("faq") || path.equals("apps") || path.startsWith("s/")) { if (forceBrowser != null) { @@ -371,6 +382,9 @@ public class Browser { } else if ("telegram.me".equals(host) || "t.me".equals(host)) { String path = uri.getPath(); if (path != null && path.length() > 1) { + if (all) { + return true; + } path = path.substring(1).toLowerCase(); if (path.equals("iv") || path.startsWith("s/")) { if (forceBrowser != null) { @@ -380,6 +394,10 @@ public class Browser { } return true; } + } else if (all) { + if (host.endsWith("telegram.org") || host.endsWith("telegra.ph") || host.endsWith("telesco.pe")) { + return true; + } } return false; } 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 0281a1cb9..6c8c57749 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -1074,7 +1074,8 @@ public class ActionBarLayout extends FrameLayout { fragment.onTransitionAnimationEnd(true, false); fragment.onBecomeFullyVisible(); }; - if (!fragment.needDelayOpenAnimation()) { + boolean noDelay; + if (noDelay = !fragment.needDelayOpenAnimation()) { if (currentFragment != null) { currentFragment.onTransitionAnimationStart(false, false); } @@ -1105,6 +1106,12 @@ public class ActionBarLayout extends FrameLayout { return; } waitingForKeyboardCloseRunnable = null; + if (!noDelay) { + if (currentFragment != null) { + currentFragment.onTransitionAnimationStart(false, false); + } + fragment.onTransitionAnimationStart(true, false); + } startLayoutAnimation(true, true, preview); } }; 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 964b5a9f6..e08db0e63 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -918,8 +918,10 @@ public class ActionBarMenuItem extends FrameLayout { } else { if (searchFieldCaption.getVisibility() == VISIBLE) { measureChildWithMargins(searchFieldCaption, widthMeasureSpec, MeasureSpec.getSize(widthMeasureSpec) / 2, heightMeasureSpec, 0); + width = searchFieldCaption.getMeasuredWidth() + AndroidUtilities.dp(4); + } else { + width = 0; } - width = 0; int minWidth = MeasureSpec.getSize(widthMeasureSpec); ignoreRequestLayout = true; measureChildWithMargins(searchFilterLayout, widthMeasureSpec, width, heightMeasureSpec, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 39a83f631..3c6350688 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -7637,7 +7637,9 @@ public class Theme { if (drawable == null) { return; } - if (drawable instanceof MsgClockDrawable) { + if (drawable instanceof StatusDrawable) { + ((StatusDrawable) drawable).setColor(color); + } else if (drawable instanceof MsgClockDrawable) { ((MsgClockDrawable) drawable).setColor(color); } else if (drawable instanceof ShapeDrawable) { ((ShapeDrawable) drawable).getPaint().setColor(color); 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 122a318db..6e7f66bb5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -676,6 +676,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { notifyDataSetChanged(); if (needMessagesSearch != 2 && delegate != null) { delegate.searchStateChanged(true, false); + } else { + waitingResponseCount--; } Utilities.searchQueue.postRunnable(searchRunnable = () -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index eb132bce5..8755fadc9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -121,7 +121,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca currentLiveLocations = new ArrayList<>(liveLocations); int uid = UserConfig.getInstance(currentAccount).getClientUserId(); for (int a = 0; a < currentLiveLocations.size(); a++) { - if (currentLiveLocations.get(a).id == uid) { + if (currentLiveLocations.get(a).id == uid || currentLiveLocations.get(a).object.out) { currentLiveLocations.remove(a); break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 2bd2de26e..84123386f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -11,7 +11,6 @@ package org.telegram.ui.Adapters; import android.content.Context; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.text.style.ForegroundColorSpan; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; @@ -316,7 +315,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { } } else if (position > searchResult.size() && un != null) { String foundUserName = searchAdapterHelper.getLastFoundUsername(); - if (foundUserName.startsWith("@")) { + if (foundUserName != null && foundUserName.startsWith("@")) { foundUserName = foundUserName.substring(1); } try { @@ -324,7 +323,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); spannableStringBuilder.append("@"); spannableStringBuilder.append(un); - if ((index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1) { + if (foundUserName != null && (index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1) { int len = foundUserName.length(); if (index == 0) { len++; 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 4f4dc2ee0..3de588c6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -3600,7 +3600,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } photoImage.setAllowStartAnimation(messageObject.gifState != 1); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - photoParentObject = document; + if (currentPhotoObject != null) { + photoParentObject = document; + } else if (photo != null) { + currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 90); + photoParentObject = photo; + } if (currentPhotoObject != null && (currentPhotoObject.w == 0 || currentPhotoObject.h == 0)) { for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); @@ -4777,13 +4782,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.isDice()) { filter = String.format(Locale.US, "%d_%d_dice_%s_%s", w, h, messageObject.getDiceEmoji(), messageObject.toString()); photoImage.setAutoRepeat(2); - TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(currentMessageObject.getDiceEmoji()); + String emoji = currentMessageObject.getDiceEmoji(); + TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(emoji); if (stickerSet != null) { if (stickerSet.documents.size() > 0) { int value = currentMessageObject.getDiceValue(); if (value <= 0) { TLRPC.Document document = stickerSet.documents.get(0); - currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 40); + if ("\uD83C\uDFB0".equals(emoji)) { + currentPhotoObjectThumb = null; + } else { + currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 40); + } photoParentObject = document; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 90733bd51..148ba7269 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -1722,6 +1722,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); MediaController.saveFilesFromMessages(getParentActivity(), getAccountInstance(), messageObjects, (count) -> { if (count > 0) { + if (getParentActivity() == null) { + return; + } BulletinFactory.of(ChatActivity.this).createDownloadBulletin(isMusic ? BulletinFactory.FileType.AUDIOS : BulletinFactory.FileType.UNKNOWNS, count).show(); } }); @@ -2435,13 +2438,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrimView != null) { canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); float listTop = chatListView.getY() + chatListViewPaddingTop - AndroidUtilities.dp(4); - if (isThreadChat()) { - float pinnedViewH = 0; - if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { - pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); - } - listTop += pinnedViewH; - } MessageObject.GroupedMessages scrimGroup; if (scrimView instanceof ChatMessageCell) { scrimGroup = ((ChatMessageCell) scrimView).getCurrentMessagesGroup(); @@ -3019,7 +3015,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (emptyViewContainer != null) { emptyViewContainer.setTranslationY(translationY / 1.7f); } - invalidate(); + invalidateChatListViewTopPadding(); } @Override @@ -3162,6 +3158,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (e != null && e.getAction() == MotionEvent.ACTION_DOWN && !startedTrackingSlidingView && !maybeStartTrackingSlidingView && slidingView == null) { View view = getPressedChildView(); if (view instanceof ChatMessageCell) { + if (slidingView != null) { + slidingView.setSlidingOffset(0); + } slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); if (chatMode != 0 || threadMessageObjects != null && threadMessageObjects.contains(message) || @@ -4045,6 +4044,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AndroidUtilities.cancelRunOnUIThread(finishRunnable); } AndroidUtilities.runOnUIThread(finishRunnable = () -> { + if (nextScrollToMessageId != 0) { + scrollToMessageId(nextScrollToMessageId, nextScrollFromMessageId, nextScrollSelect, nextScrollLoadIndex, nextScrollForce); + nextScrollToMessageId = 0; + } if (index != -1) { getNotificationCenter().onAnimationFinish(index); index = -1; @@ -4082,7 +4085,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public int getStarForFixGap() { - return chatListViewPaddingTop; + int padding = chatListViewPaddingTop; + if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); + } + return padding; } @Override @@ -4209,9 +4216,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int n = chatListView.getChildCount(); for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); + int padding = chatListViewPaddingTop; + if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); + } if (chatListView.getChildAdapterPosition(child) == chatAdapter.getItemCount() - 1) { - if (child.getTop() - dy > chatListViewPaddingTop) { - dy = child.getTop() - chatListViewPaddingTop; + if (child.getTop() - dy > padding) { + dy = child.getTop() - padding; } return super.scrollVerticallyBy(dy, recycler, state); } @@ -4492,20 +4503,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedMessageView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); contentView.addView(pinnedMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); pinnedMessageView.setOnClickListener(v -> { - if (chatListView.isFastScrollAnimationRunning()) { + if (chatListView.isFastScrollAnimationRunning()) { //TODO remove later return; } wasManualScroll = true; if (isThreadChat()) { scrollToMessageId(threadMessageId, 0, true, 0, true); } else if (currentPinnedMessageId != 0) { - scrollToMessageId(currentPinnedMessageId, 0, true, 0, true); + int currentPinned; + /*if (forceNextPinnedMessageId != 0 && chatListView.isFastScrollAnimationRunning()) { + currentPinned = findClosest(pinnedMessageIds, forceNextPinnedMessageId, currentPinnedMessageIndex); + } else {*/ + currentPinned = currentPinnedMessageId; + //} + scrollToMessageId(currentPinned, 0, true, 0, true); if (!pinnedMessageIds.isEmpty()) { - if (currentPinnedMessageId == pinnedMessageIds.get(pinnedMessageIds.size() - 1)) { + if (currentPinned == pinnedMessageIds.get(pinnedMessageIds.size() - 1)) { forceNextPinnedMessageId = pinnedMessageIds.get(0) + 1; forceScrollToFirst = true; } else { - forceNextPinnedMessageId = currentPinnedMessageId - 1; + forceNextPinnedMessageId = currentPinned - 1; forceScrollToFirst = false; } updateMessagesVisiblePart(false); @@ -6275,9 +6292,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); searchUpButton.setOnClickListener(view -> { - if (chatListView.isFastScrollAnimationRunning()) { - return; - } getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) { @@ -6295,9 +6309,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); searchDownButton.setOnClickListener(view -> { - if (chatListView.isFastScrollAnimationRunning()) { - return; - } getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); }); @@ -6900,7 +6911,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); float pinnedViewH = 0; - if (!isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } int oldPadding = chatListViewPaddingTop; @@ -6910,7 +6921,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListViewPaddingTop += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); } if (!inPreviewMode && chatActivityEnterView != null) { - chatListViewPaddingTop += chatActivityEnterView.getHeightWithTopView() - AndroidUtilities.dp(51) - chatActivityEnterView.getAnimatedTop(); + if (chatActivityEnterView.getAnimatedTop() != 0) { + chatListViewPaddingTop += chatActivityEnterView.getHeightWithTopView() - AndroidUtilities.dp(51) - chatActivityEnterView.getAnimatedTop(); + } else { + chatListViewPaddingTop -= chatListView.getTranslationY(); + } } int p = chatListView.getMeasuredHeight() * 2 / 3; @@ -6957,8 +6972,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View child = chatListView.getChildAt(i); int adapterPosition = chatListView.getChildAdapterPosition(child); if (adapterPosition == chatAdapter.getItemCount() - 1) { - if (child.getTop() > chatListViewPaddingTop) { - chatListView.scrollBy(0, child.getTop() - chatListViewPaddingTop); + int padding = chatListViewPaddingTop; + if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { + padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); + } + if (child.getTop() > padding) { + chatListView.scrollBy(0, child.getTop() - padding); } break; } @@ -9609,7 +9628,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!pinnedMessageIds.isEmpty()) { - currentPinnedMessageId = findClosest(pinnedMessageIds, forceNextPinnedMessageId != 0 && (maxVisibleId > forceNextPinnedMessageId || forceScrollToFirst || chatListView.isFastScrollAnimationRunning()) ? forceNextPinnedMessageId : maxVisibleId, currentPinnedMessageIndex); + currentPinnedMessageId = findClosest(pinnedMessageIds, forceNextPinnedMessageId != 0 && (maxVisibleId > forceNextPinnedMessageId || forceScrollToFirst || chatListView.isFastScrollAnimationRunning() || postponedScrollToLastMessageQueryIndex != 0) ? forceNextPinnedMessageId : maxVisibleId, currentPinnedMessageIndex); if (!loadingPinnedMessagesList && !pinnedEndReached && !pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2) { getMediaDataController().loadPinnedMessages(dialog_id, pinnedMessageIds.get(pinnedMessageIds.size() - 1), 0); loadingPinnedMessagesList = true; @@ -9917,9 +9936,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private AlertDialog progressDialog; + private int nextScrollToMessageId; + private int nextScrollFromMessageId; + private boolean nextScrollSelect; + private int nextScrollLoadIndex; + private boolean nextScrollForce; public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean forceScroll) { if (id == 0 || chatListView.isFastScrollAnimationRunning() || (chatListItemAniamtor != null && chatListItemAniamtor.isRunning()) || getParentActivity() == null) { + if (id != 0 && getParentActivity() != null) { + nextScrollToMessageId = id; + nextScrollFromMessageId = fromMessageId; + nextScrollSelect = select; + nextScrollLoadIndex = loadIndex; + nextScrollForce = forceScroll; + } return; } @@ -11127,14 +11158,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not doNotRemoveLoadIndex = false; } if (!doNotRemoveLoadIndex && !openAnimationEnded) { - getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, - NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); + int[] alowedNotifications = new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, + NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}; + if (transitionAnimationIndex == 0) { + transitionAnimationIndex = getNotificationCenter().setAnimationInProgress(transitionAnimationIndex, alowedNotifications); + } else { + getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, alowedNotifications); + } } int index = waitingForLoad.indexOf(queryLoadIndex); int currentUserId = getUserConfig().getClientUserId(); int mode = (Integer) args[14]; boolean isCache = (Boolean) args[3]; boolean postponedScroll = postponedScrollToLastMessageQueryIndex > 0 && queryLoadIndex == postponedScrollToLastMessageQueryIndex; + if (postponedScroll) { + postponedScrollToLastMessageQueryIndex = 0; + } if (index == -1) { if (chatMode == MODE_SCHEDULED && mode == MODE_SCHEDULED && !isCache) { @@ -14905,7 +14944,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onTransitionAnimationStart(boolean isOpen, boolean backward) { int[] alowedNotifications = null; if (isOpen) { - if (threadMessageId != 0) { + if (transitionAnimationIndex == 0) { alowedNotifications = new int[]{ NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.needDeleteDialog, @@ -14964,13 +15003,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } fixedKeyboardHeight = -1; - getNotificationCenter().onAnimationFinish(transitionAnimationIndex); if (isOpen) { if (blurredView != null && blurredView.getVisibility() == View.VISIBLE) { blurredView.setVisibility(View.GONE); blurredView.setBackground(null); } openAnimationEnded = true; + getNotificationCenter().onAnimationFinish(transitionAnimationIndex); if (Build.VERSION.SDK_INT >= 21) { createChatAttachView(); } @@ -15051,6 +15090,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } firstOpen = false; } + } else { + getNotificationCenter().onAnimationFinish(transitionAnimationIndex); } } @@ -16868,6 +16909,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (textSelectionHint != null) { textSelectionHint.hide(); } + if (chatActivityEnterView != null) { + chatActivityEnterView.preventInput = false; + } textSelectionHintWasShowed = false; } @@ -17585,6 +17629,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (topUndoView != null) { topUndoView.hide(true, 1); } + if (undoView != null) { + undoView.hide(true, 1); + } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } @@ -17642,6 +17689,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not addToSelectedMessages(message, listView); + if (chatActivityEnterView != null) { + chatActivityEnterView.preventInput = true; + } + selectedMessagesCountTextView.setNumber(selectedMessagesIds[0].size() + selectedMessagesIds[1].size(), false); updateVisibleRows(); } @@ -20987,7 +21038,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().onAnimationFinish(animationIndex)); + AndroidUtilities.runOnUIThread(() -> { + if (nextScrollToMessageId != 0) { + scrollToMessageId(nextScrollToMessageId, nextScrollFromMessageId, nextScrollSelect, nextScrollLoadIndex, nextScrollForce); + nextScrollToMessageId = 0; + } + getNotificationCenter().onAnimationFinish(animationIndex); + }); } @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 a8e91cd69..055361dbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -757,7 +757,6 @@ public final class Bulletin { linearLayout.addView(titleTextView); subtitleTextView = new TextView(context); - subtitleTextView.setMaxLines(2); subtitleTextView.setTextColor(undoInfoColor); subtitleTextView.setTypeface(Typeface.SANS_SERIF); subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); 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 5d7f2acd6..6b2746381 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -227,6 +227,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private AdjustPanLayoutHelper adjustPanLayoutHelper; private Runnable showTopViewRunnable; private Runnable setTextFieldRunnable; + public boolean preventInput; private class SeekBarWaveformView extends View { @@ -2056,6 +2057,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe return false; } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (preventInput) { + return false; + } + return super.dispatchKeyEvent(event); + } + @Override protected void onSelectionChanged(int selStart, int selEnd) { super.onSelectionChanged(selStart, selEnd); @@ -3899,27 +3908,32 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } exitAnimation.setDuration(200); - attachButton.setAlpha(0f); + AnimatorSet attachIconAnimator; + if (attachButton != null) { + attachButton.setAlpha(0f); + attachButton.setScaleX(0); + attachButton.setScaleY(0); + + attachIconAnimator = new AnimatorSet(); + attachIconAnimator.playTogether( + ObjectAnimator.ofFloat(attachButton, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(attachButton, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(attachButton, View.SCALE_Y, 1.0f) + ); + attachIconAnimator.setDuration(150); + } else { + attachIconAnimator = null; + } + emojiButton[0].setAlpha(0f); emojiButton[1].setAlpha(0f); - attachButton.setScaleX(0); emojiButton[0].setScaleX(0); emojiButton[1].setScaleX(0); - attachButton.setScaleY(0); emojiButton[0].setScaleY(0); emojiButton[1].setScaleY(0); - AnimatorSet attachIconAnimator = new AnimatorSet(); - attachIconAnimator.playTogether( - ObjectAnimator.ofFloat(attachButton, View.ALPHA, 1.0f), - ObjectAnimator.ofFloat(attachButton, View.SCALE_X, 1.0f), - ObjectAnimator.ofFloat(attachButton, View.SCALE_Y, 1.0f) - ); - - attachIconAnimator.setDuration(150); - AnimatorSet iconsEndAnimator = new AnimatorSet(); iconsEndAnimator.playTogether( @@ -3940,12 +3954,18 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe iconsEndAnimator.setStartDelay(600); recordPannelAnimation = new AnimatorSet(); - recordPannelAnimation.playTogether( - exitAnimation, - attachIconAnimator, - iconsEndAnimator - - ); + if (attachIconAnimator != null) { + recordPannelAnimation.playTogether( + exitAnimation, + attachIconAnimator, + iconsEndAnimator + ); + } else { + recordPannelAnimation.playTogether( + exitAnimation, + iconsEndAnimator + ); + } recordPannelAnimation.addListener(new AnimatorListenerAdapter() { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java index a68142226..537756d79 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java @@ -245,6 +245,7 @@ public class ProximitySheet extends FrameLayout { buttonTextView.setGravity(Gravity.CENTER); buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setMaxLines(2); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); buttonContainer.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); @@ -319,8 +320,8 @@ public class ProximitySheet extends FrameLayout { } else { String format = LocaleController.getString("LocationNotifiationButtonUser", R.string.LocationNotifiationButtonUser); int width = (int) Math.ceil(buttonTextView.getPaint().measureText(format)); - int restWidth = totalWidth - AndroidUtilities.dp(32 + 62) - width; - CharSequence name = TextUtils.ellipsize(UserObject.getFirstName(currentUser), buttonTextView.getPaint(), restWidth, TextUtils.TruncateAt.END); + int restWidth = (int) ((totalWidth - AndroidUtilities.dp(32 + 62)) * 1.5f - width); + CharSequence name = TextUtils.ellipsize(UserObject.getFirstName(currentUser), buttonTextView.getPaint(), Math.max(AndroidUtilities.dp(10), restWidth), TextUtils.TruncateAt.END); buttonTextView.setText(LocaleController.formatString("LocationNotifiationButtonUser", R.string.LocationNotifiationButtonUser, name, distance)); } if (buttonTextView.getTag() != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java index 52871e831..102fa0064 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java @@ -20,6 +20,10 @@ public class RLottieImageView extends ImageView { super(context); } + public void clearLayerColors() { + layerColors.clear(); + } + public void setLayerColor(String layer, int color) { if (layerColors == null) { layerColors = new HashMap<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java index 4d133ff05..b504426f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerAnimationScrollHelper.java @@ -10,6 +10,8 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.SharedConfig; import org.telegram.ui.Cells.ChatMessageCell; import java.util.ArrayList; @@ -57,7 +59,7 @@ public class RecyclerAnimationScrollHelper { } int n = recyclerView.getChildCount(); - if (n == 0) { + if (n == 0 || !MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)) { layoutManager.scrollToPositionWithOffset(position, offset, bottom); return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index 6e222ab59..dac841bbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -104,6 +104,8 @@ public class UndoView extends FrameLayout { public final static int ACTION_REMOVED_FROM_FOLDER = 21; public final static int ACTION_PROFILE_PHOTO_CHANGED = 22; public final static int ACTION_CHAT_UNARCHIVED = 23; + public final static int ACTION_PROXIMITY_SET = 24; + public final static int ACTION_PROXIMITY_REMOVED = 25; private CharSequence infoText; @@ -233,13 +235,13 @@ public class UndoView extends FrameLayout { } private boolean hasSubInfo() { - return currentAction == ACTION_QR_SESSION_ACCEPTED || currentAction == ACTION_ARCHIVE_HIDDEN || currentAction == ACTION_ARCHIVE_HINT || currentAction == ACTION_ARCHIVE_FEW_HINT || + return currentAction == ACTION_QR_SESSION_ACCEPTED || currentAction == ACTION_PROXIMITY_SET || currentAction == ACTION_ARCHIVE_HIDDEN || currentAction == ACTION_ARCHIVE_HINT || currentAction == ACTION_ARCHIVE_FEW_HINT || currentAction == ACTION_QUIZ_CORRECT || currentAction == ACTION_QUIZ_INCORRECT || currentAction == ACTION_ARCHIVE_PINNED && MessagesController.getInstance(currentAccount).dialogFilters.isEmpty(); } public boolean isMultilineSubInfo() { - return currentAction == ACTION_THEME_CHANGED || currentAction == ACTION_FILTERS_AVAILABLE; + return currentAction == ACTION_THEME_CHANGED || currentAction == ACTION_FILTERS_AVAILABLE || currentAction == ACTION_PROXIMITY_SET; } public void setAdditionalTranslationY(float value) { @@ -512,6 +514,59 @@ public class UndoView extends FrameLayout { leftImageView.setProgress(0); leftImageView.playAnimation(); } + } else if (currentAction == ACTION_PROXIMITY_SET || currentAction == ACTION_PROXIMITY_REMOVED) { + int radius = (Integer) infoObject; + TLRPC.User user = (TLRPC.User) infoObject2; + + undoImageView.setVisibility(GONE); + leftImageView.setVisibility(VISIBLE); + + if (radius != 0) { + infoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + leftImageView.clearLayerColors(); + leftImageView.setLayerColor("BODY.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Wibe Big.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Wibe Big 3.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Wibe Small.**", Theme.getColor(Theme.key_undo_infoColor)); + + infoTextView.setText(LocaleController.getString("ProximityAlertSet", R.string.ProximityAlertSet)); + leftImageView.setAnimation(R.raw.ic_unmute, 28, 28); + subinfoTextView.setVisibility(VISIBLE); + subinfoTextView.setSingleLine(false); + subinfoTextView.setMaxLines(3); + + if (user != null) { + subinfoTextView.setText(LocaleController.formatString("ProximityAlertSetInfoUser", R.string.ProximityAlertSetInfoUser, UserObject.getFirstName(user), LocaleController.formatDistance(radius, 2))); + } else { + subinfoTextView.setText(LocaleController.formatString("ProximityAlertSetInfoGroup2", R.string.ProximityAlertSetInfoGroup2, LocaleController.formatDistance(radius, 2))); + } + undoButton.setVisibility(GONE); + + layoutParams.topMargin = AndroidUtilities.dp(6); + } else { + infoTextView.setTypeface(Typeface.DEFAULT); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + leftImageView.clearLayerColors(); + leftImageView.setLayerColor("Body Main.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Body Top.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Line.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Curve Big.**", Theme.getColor(Theme.key_undo_infoColor)); + leftImageView.setLayerColor("Curve Small.**", Theme.getColor(Theme.key_undo_infoColor)); + + layoutParams.topMargin = AndroidUtilities.dp(14); + + infoTextView.setText(LocaleController.getString("ProximityAlertCancelled", R.string.ProximityAlertCancelled)); + leftImageView.setAnimation(R.raw.ic_mute, 28, 28); + subinfoTextView.setVisibility(GONE); + undoTextView.setTextColor(Theme.getColor(Theme.key_undo_cancelColor)); + undoButton.setVisibility(VISIBLE); + } + + layoutParams.leftMargin = AndroidUtilities.dp(58); + + leftImageView.setProgress(0); + leftImageView.playAnimation(); } else if (currentAction == ACTION_QR_SESSION_ACCEPTED) { TLRPC.TL_authorization authorization = (TLRPC.TL_authorization) infoObject; @@ -738,6 +793,8 @@ public class UndoView extends FrameLayout { undoViewHeight = infoTextView.getMeasuredHeight() + AndroidUtilities.dp(currentAction == ACTION_DICE_INFO || currentAction == ACTION_DICE_NO_SEND_INFO || currentAction == ACTION_TEXT_INFO ? 14 : 28); if (currentAction == ACTION_TEXT_INFO) { undoViewHeight = Math.max(undoViewHeight, AndroidUtilities.dp(52)); + } else if (currentAction == ACTION_PROXIMITY_REMOVED) { + undoViewHeight = Math.max(undoViewHeight, AndroidUtilities.dp(50)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index ebe1cff79..349f7951a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -99,8 +99,6 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente String lastMessagesSearchString; String lastSearchFilterQueryString; - int currentAccount = UserConfig.selectedAccount; - FiltersView.MediaFilterData currentSearchFilter; int currentSearchDialogId; long currentSearchMaxDate; @@ -485,6 +483,8 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente final int folderId = uiCallback.getFolderId(); + int currentAccount = UserConfig.selectedAccount; + AndroidUtilities.runOnUIThread(searchRunnable = () -> { TLObject request; @@ -810,7 +810,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente for (int j = 0; j < messages.size(); j++) { MessageObject messageObject = messages.get(j); long dialogId = messageObject.getDialogId(); - int currentChannelId = dialogId < 0 && ChatObject.isChannel((int) -dialogId, currentAccount) ? (int) -dialogId : 0; + int currentChannelId = dialogId < 0 && ChatObject.isChannel((int) -dialogId, UserConfig.selectedAccount) ? (int) -dialogId : 0; if (currentChannelId == channelId) { for (int i = 0; i < markAsDeletedMessages.size(); i++) { if (messageObject.getId() == markAsDeletedMessages.get(i)) { @@ -989,10 +989,10 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente AndroidUtilities.openDocument(message, parentActivity, parentFragment); } else if (!cell.isLoading()) { MessageObject messageObject = cell.getMessage(); - AccountInstance.getInstance(currentAccount).getFileLoader().loadFile(document, messageObject, 0, 0); + AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().loadFile(document, messageObject, 0, 0); cell.updateFileExistIcon(); } else { - AccountInstance.getInstance(currentAccount).getFileLoader().cancelLoadFile(document); + AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().cancelLoadFile(document); cell.updateFileExistIcon(); } } @@ -1407,16 +1407,18 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente EmbedBottomSheet.show(parentActivity, webPage.site_name, webPage.description, webPage.url, webPage.embed_url, webPage.embed_width, webPage.embed_height, false); } + int lastAccount; + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getInstance(lastAccount = UserConfig.selectedAccount).addObserver(this, NotificationCenter.emojiDidLoad); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getInstance(lastAccount).removeObserver(this, NotificationCenter.emojiDidLoad); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index 612b24d75..f272c0a7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -117,6 +117,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MapPlaceholderDrawable; import org.telegram.ui.Components.ProximitySheet; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.UndoView; import java.io.File; import java.util.ArrayList; @@ -145,6 +146,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private MapOverlayView overlayView; private HintView hintView; + private UndoView[] undoView = new UndoView[2]; + private boolean canUndo; + private boolean proximityAnimationInProgress; private GoogleMap googleMap; @@ -465,6 +469,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } catch (Exception e) { FileLog.e(e); } + if (undoView[0] != null) { + undoView[0].hide(true, 0); + } if (adapter != null) { adapter.destroy(); } @@ -481,6 +488,18 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } + private UndoView getUndoView() { + if (undoView[0].getVisibility() == View.VISIBLE) { + UndoView old = undoView[0]; + undoView[0] = undoView[1]; + undoView[1] = old; + old.hide(true, 2); + mapViewClip.removeView(undoView[0]); + mapViewClip.addView(undoView[0]); + } + return undoView[0]; + } + @Override public boolean isSwipeBackEnabled(MotionEvent event) { return false; @@ -842,10 +861,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } }); } + proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); proximityButton.setBackgroundDrawable(drawable); - proximityButton.setImageResource(R.drawable.msg_location_alert); proximityButton.setScaleType(ImageView.ScaleType.CENTER); - proximityButton.setTag(Theme.key_location_actionIcon); proximityButton.setContentDescription(LocaleController.getString("AccDescrLocationNotify", R.string.AccDescrLocationNotify)); mapViewClip.addView(proximityButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.TOP, 0, 12 + 50, 12, 0)); proximityButton.setOnClickListener(v -> { @@ -858,13 +876,25 @@ public class LocationActivity extends BaseFragment implements NotificationCenter SharedPreferences preferences = MessagesController.getGlobalMainSettings(); preferences.edit().putInt("proximityhint", 3).commit(); LocationController.SharingLocationInfo info = getLocationController().getSharingLocationInfo(dialogId); + if (canUndo) { + undoView[0].hide(true, 1); + } if (info != null && info.proximityMeters > 0) { - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); - getLocationController().setProximityLocation(dialogId, 0, true); + proximityButton.setImageResource(R.drawable.msg_location_alert); if (proximityCircle != null) { proximityCircle.remove(); proximityCircle = null; } + canUndo = true; + getUndoView().showWithAction(0, UndoView.ACTION_PROXIMITY_REMOVED, 0, null, + () -> { + getLocationController().setProximityLocation(dialogId, 0, true); + canUndo = false; + }, () -> { + proximityButton.setImageResource(R.drawable.msg_location_alert2); + createCircle(info.proximityMeters); + canUndo = false; + }); return; } openProximityAlert(); @@ -875,10 +905,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } if (messageObject == null || !messageObject.isLiveLocation() || messageObject.isExpiredLiveLocation(getConnectionsManager().getCurrentTime()) || ChatObject.isChannel(chat) && !chat.megagroup) { proximityButton.setVisibility(View.GONE); + proximityButton.setImageResource(R.drawable.msg_location_alert); } else { LocationController.SharingLocationInfo myInfo = getLocationController().getSharingLocationInfo(dialogId); if (myInfo != null && myInfo.proximityMeters > 0) { - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + proximityButton.setImageResource(R.drawable.msg_location_alert2); } else { if ((int) dialogId > 0 && messageObject.getFromChatId() == getUserConfig().getClientUserId()) { proximityButton.setVisibility(View.INVISIBLE); @@ -886,7 +917,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter proximityButton.setScaleX(0.4f); proximityButton.setScaleY(0.4f); } - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); + proximityButton.setImageResource(R.drawable.msg_location_alert); } } @@ -1244,6 +1275,16 @@ public class LocationActivity extends BaseFragment implements NotificationCenter adapter.setMessageObject(messageObject); } + + for (int a = 0; a < 2; a++) { + undoView[a] = new UndoView(context); + undoView[a].setAdditionalTranslationY(AndroidUtilities.dp(10)); + if (Build.VERSION.SDK_INT >= 21) { + undoView[a].setTranslationZ(AndroidUtilities.dp(5)); + } + mapViewClip.addView(undoView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); + } + shadow = new View(context) { private RectF rect = new RectF(); @@ -1264,6 +1305,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } }; + if (Build.VERSION.SDK_INT >= 21) { + shadow.setTranslationZ(AndroidUtilities.dp(6)); + } mapViewClip.addView(shadow, layoutParams); if (messageObject == null && chatLocation == null && initialLocation != null) { @@ -1389,9 +1433,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter previousRadius = proximityCircle.getRadius(); } - TLRPC.User user = null; + TLRPC.User user; if ((int) dialogId > 0) { user = getMessagesController().getUser((int) dialogId); + } else { + user = null; } proximitySheet = new ProximitySheet(getParentActivity(), user, (move, radius) -> { if (proximityCircle != null) { @@ -1423,13 +1469,14 @@ public class LocationActivity extends BaseFragment implements NotificationCenter AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("ShareLocationAlertTitle", R.string.ShareLocationAlertTitle)); builder.setMessage(LocaleController.getString("ShareLocationAlertText", R.string.ShareLocationAlertText)); - builder.setPositiveButton(LocaleController.getString("ShareLocationAlertButton", R.string.ShareLocationAlertButton), (dialog, id) -> shareLiveLocation(900, radius)); + builder.setPositiveButton(LocaleController.getString("ShareLocationAlertButton", R.string.ShareLocationAlertButton), (dialog, id) -> shareLiveLocation(user, 900, radius)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); return false; } proximitySheet.setRadiusSet(); - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + proximityButton.setImageResource(R.drawable.msg_location_alert2); + getUndoView().showWithAction(0, UndoView.ACTION_PROXIMITY_SET, radius, user, null, null); getLocationController().setProximityLocation(dialogId, radius, true); return true; }, () -> { @@ -1469,14 +1516,16 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } } - TLRPC.User user = null; + TLRPC.User user; if ((int) dialogId > 0) { user = getMessagesController().getUser((int) dialogId); + } else { + user = null; } - showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> shareLiveLocation(param, proximityRadius))); + showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> shareLiveLocation(user, param, proximityRadius))); } - private void shareLiveLocation(int period, int proximityRadius) { + private void shareLiveLocation(TLRPC.User user, int period, int radius) { TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); location.geo = new TLRPC.TL_geoPoint(); location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); @@ -1484,15 +1533,16 @@ public class LocationActivity extends BaseFragment implements NotificationCenter location.heading = LocationController.getHeading(myLocation); location.flags |= 1; location.period = period; - location.proximity_notification_radius = proximityRadius; + location.proximity_notification_radius = radius; location.flags |= 8; delegate.didSelectLocation(location, locationType, true, 0); - if (proximityRadius > 0) { + if (radius > 0) { proximitySheet.setRadiusSet(); - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); + proximityButton.setImageResource(R.drawable.msg_location_alert2); if (proximitySheet != null) { proximitySheet.dismiss(); } + getUndoView().showWithAction(0, UndoView.ACTION_PROXIMITY_SET, radius, user, null, null); } else { finishFragment(); } @@ -2180,7 +2230,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter bounds = builder.build(); if (messages.size() > 1) { try { - moveToBounds = CameraUpdateFactory.newLatLngBounds(bounds, AndroidUtilities.dp(80)); + moveToBounds = CameraUpdateFactory.newLatLngBounds(bounds, AndroidUtilities.dp(80 + 33)); googleMap.moveCamera(moveToBounds); moveToBounds = null; } catch (Exception e) { @@ -2359,7 +2409,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { int lowerId = (int) messageObject.getDialogId(); if (lowerId > 0) { - proximityButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); + proximityButton.setImageResource(R.drawable.msg_location_alert); if (proximityCircle != null) { proximityCircle.remove(); proximityCircle = null; @@ -2429,6 +2479,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter FileLog.e(e); } } + if (undoView[0] != null) { + undoView[0].hide(true, 0); + } onResumeCalled = false; } @@ -2441,6 +2494,13 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return super.onBackPressed(); } + @Override + protected void onBecomeFullyHidden() { + if (undoView[0] != null) { + undoView[0].hide(true, 0); + } + } + @Override public void onResume() { super.onResume(); @@ -2543,6 +2603,25 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } }; + for (int a = 0; a < undoView.length; a++) { + themeDescriptions.add(new ThemeDescription(undoView[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_undo_background)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"undoImageView"}, null, null, null, Theme.key_undo_cancelColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"undoTextView"}, null, null, null, Theme.key_undo_cancelColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"subinfoTextView"}, null, null, null, Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"textPaint"}, null, null, null, Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"progressPaint"}, null, null, null, Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "BODY", Theme.key_undo_background)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Wibe Big", Theme.key_undo_background)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Wibe Big 3", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Wibe Small", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Body Main.**", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Body Top.**", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Line.**", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Curve Big.**", Theme.key_undo_infoColor)); + themeDescriptions.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Curve Small.**", Theme.key_undo_infoColor)); + } + themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, cellDelegate, Theme.key_dialogBackground)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_dialogBackground)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 29fd10777..6f47cf86d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -5677,56 +5677,57 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. req.flags |= 4; } getConnectionsManager().sendRequest(req, (response, error) -> { - if (error == null) { - TLRPC.User user = getMessagesController().getUser(getUserConfig().getClientUserId()); - if (user == null) { - user = getUserConfig().getCurrentUser(); - if (user == null) { - return; - } - getMessagesController().putUser(user, false); - } else { - getUserConfig().setCurrentUser(user); - } - TLRPC.TL_photos_photo photos_photo = (TLRPC.TL_photos_photo) response; - ArrayList sizes = photos_photo.photo.sizes; - TLRPC.PhotoSize small = FileLoader.getClosestPhotoSizeWithSize(sizes, 150); - TLRPC.PhotoSize big = FileLoader.getClosestPhotoSizeWithSize(sizes, 800); - TLRPC.VideoSize videoSize = photos_photo.photo.video_sizes.isEmpty() ? null : photos_photo.photo.video_sizes.get(0); - user.photo = new TLRPC.TL_userProfilePhoto(); - user.photo.photo_id = photos_photo.photo.id; - if (small != null) { - user.photo.photo_small = small.location; - } - if (big != null) { - user.photo.photo_big = big.location; - } - - if (small != null && avatar != null) { - File destFile = FileLoader.getPathToAttach(small, true); - File src = FileLoader.getPathToAttach(avatar, true); - src.renameTo(destFile); - String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; - String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUser(user, false), true); - } - if (big != null && avatarBig != null) { - File destFile = FileLoader.getPathToAttach(big, true); - File src = FileLoader.getPathToAttach(avatarBig, true); - src.renameTo(destFile); - } - if (videoSize != null && videoPath != null) { - File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); - File src = new File(videoPath); - src.renameTo(destFile); - } - - getMessagesStorage().clearUserPhotos(user.id); - ArrayList users = new ArrayList<>(); - users.add(user); - getMessagesStorage().putUsersAndChats(users, null, false, true); - } AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.User user = getMessagesController().getUser(getUserConfig().getClientUserId()); + if (user == null) { + user = getUserConfig().getCurrentUser(); + if (user == null) { + return; + } + getMessagesController().putUser(user, false); + } else { + getUserConfig().setCurrentUser(user); + } + TLRPC.TL_photos_photo photos_photo = (TLRPC.TL_photos_photo) response; + ArrayList sizes = photos_photo.photo.sizes; + TLRPC.PhotoSize small = FileLoader.getClosestPhotoSizeWithSize(sizes, 150); + TLRPC.PhotoSize big = FileLoader.getClosestPhotoSizeWithSize(sizes, 800); + TLRPC.VideoSize videoSize = photos_photo.photo.video_sizes.isEmpty() ? null : photos_photo.photo.video_sizes.get(0); + user.photo = new TLRPC.TL_userProfilePhoto(); + user.photo.photo_id = photos_photo.photo.id; + if (small != null) { + user.photo.photo_small = small.location; + } + if (big != null) { + user.photo.photo_big = big.location; + } + + if (small != null && avatar != null) { + File destFile = FileLoader.getPathToAttach(small, true); + File src = FileLoader.getPathToAttach(avatar, true); + src.renameTo(destFile); + String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; + String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUser(user, false), true); + } + if (big != null && avatarBig != null) { + File destFile = FileLoader.getPathToAttach(big, true); + File src = FileLoader.getPathToAttach(avatarBig, true); + src.renameTo(destFile); + } + if (videoSize != null && videoPath != null) { + File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); + File src = new File(videoPath); + src.renameTo(destFile); + } + + getMessagesStorage().clearUserPhotos(user.id); + ArrayList users = new ArrayList<>(); + users.add(user); + getMessagesStorage().putUsersAndChats(users, null, false, true); + } + allowPullingDown = !AndroidUtilities.isTablet() && !isInLandscapeMode && avatarImage.getImageReceiver().hasNotThumb(); avatar = null; avatarBig = null; diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4f2155d89d50515f4a199623bc6d5873f918d4 GIT binary patch literal 730 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBSkfJR9T^xl_H+M9WCijqQX@Rm ze0>?TfNTy1#`a7G79fieh^2s-fq`iO6I?`P0W*RPlH@#g@EA~uucwP+NCfBG>AUq= z0!5CM+dh(&TASg)@t?7mFGSn=Xc)M6ql)$t54OsQ9su~ZL;RStJTXLJN=noSsfIuVDz@DR=VzB z!#wYRn#Oj)3HHpZN^iYNewtt(WcB7@wyR)1`+Kjo1>%m8YmP1R72s>&SI|}IN)X*K z>%PdyZU2{*f!!rP^~uZn)f?P=1qr=&=1#cY`SzzzYIaB2*;xMO?FlxIY+e@{22B3GWQ(nW98(ZaURrqc3eF(u zpAOe9{Ap3hVOX!=xp`jgqTO#LSE!lvI6-QsS%!O zzP=1vKsE;hV|yk83y{SK#8N=az`(SC2`(bBfEmFCNgn(gJ{_odwWo_?hzIY}DQC4^ z0!0oyUwG_zUu$dY#tA~cVN-gSs&LQJIq`@8)VV{4F5U9#6w(fKyQyh zCdGfxm7ITF`o8+Ho%Yi!>x<8Sw|#$hw$sD-PQx^*XLWl`jv5!REY1_I5&pocB%Nn- zVp+lR*gPNR*h@<1Qg>`K4D2^p`Z2*bP%zIyMefi~zNkkfPegXBS2U;uDL7|s3#{gN zu6To~(x-U?&v}KSY1t0f1h#Yb{&r}8QvXpT+(ET2=A7=EM8MDvkNLt;fE>%CCsyO9zL>MLZ5JzpK4vF#v3 zcm(6l#1(5M@8GzncCTSg-mdKI;Vst0N35+lmGw# literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png new file mode 100644 index 0000000000000000000000000000000000000000..2c556f1b4eb770b4585d5597f6b0f7572849dcbb GIT binary patch literal 948 zcmV;l155mgP)TnkBA!ZS*cap zzzV_E#>Pg}Mhh)$wA?j?A3*Z~lr%<+*eD1JHi8H?A~vSd2&Pdi#6XnwcVI70&d%%s75U^B0Y+))=MjNG4lAOUDuzrw7`x*PpcbXR#rn ztiW3j5pNOLjeJ97>Oq#8d=! zlL5lM;g2YfmL?erKoV;a=dpbX?tvB<2b;kJI0K#lEuT>A4sj?wP7+fQp+v-)2Ft*e z=OMo=<7CWL!~tUIB2H%^848lI2w4eNUWamL8z<{sH?!03#3aE_pNV5J{>io^UUEq5 zrnv|lEqe0@KY-C&h1*iWPkhQXX-4 zC?cQfp8$(W--cXA>DF|c&F1PFMWeA(^@H7%0{WgPA+kiKq#_i*b3MSZFS7Hp?lZ9Vpzp(`f5q$Q5q?=u+kjl1@o0x4PH@g-X zx}98~%G%829pH-h5c>$=RM|@S^7ZK;FzYg>y$YhfFko*w6Mf0cDo8A!3ANlxiA#`d zE3wf+fP^#HUG~_@^Zd9+Z&58{bVwPti6?jTj?$-h2`C@9et`9qd<979FfZ^VK^$gTAP|v{M8TbR= WhDOGl|D{;~0000*XNP)O}2^>Z7G!p>r!p)EN!c(w$z`W&-|}i@lLEE zWd(E<7C(x|L+i*2QYJvWuWw>yKl-S(RJ>$nNSQY2VEt^?Eu6QZOrV204v)*Jbsn`E zYC74t4YkXW=8tCe9CtZZY3UM33dP+g75h_|1@xi!DU|9lU+O9p1?jZq-(h@*W4;q5 z4S8xT(KFRy*Njof1nG9Tuj#yLn=7A$k1;i5GS-kkNB`8Hn2Z^q&NejKP)}Yaom(?B zrxbtPZWR8xhL>aFIhk2DmKZM^_eiMnW6l@Y)XZ%xMt307m);@Tx?Gr{&K$H0$=)|T zX-%v9prn(;^~10{5q1Fepe0ED$<~if@izIw(T6AC33vjYfG6Mycmke4&IEn|KyCOM T*q!Bo00000NkvXXu0mjf=ded* literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 55de266d2..78f356442 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -210,7 +210,7 @@ مائل رمز يتوسطه خط - خط سفلي + تسطير عادي يحتاج **تيليجرام** إلى الوصول لجهات اتصالك لكي تتمكن من التواصل مع أصدقائك عبر جميع أجهزتك، ستتم مزامنة جهات اتصالك باستمرار مع خوادم تيليجرام السحابية شديدة التشفير. ليس الآن @@ -228,26 +228,29 @@ اذهب إلى الإعدادات عرض الملف الشخصي فتح القناة + فتح المجموعة إرسال رسالة إشارة - Notifications muted - Notifications muted for %1$s - Notifications unmuted - %1$d messages deleted - Message deleted - %1$d messages deleted - %1$d messages deleted - %1$d messages deleted - %1$d messages deleted + تم كتم الإشعارات + الإشعارات مكتومة لـ %1$s + تم إلغاء كتم الإشعارات + تم حذف %1$d رسالة + تم حذف %1$d رسالة + تم حذف رسالتين + تم حذف %1$d رسائل + تم حذف %1$d رسالة + تم حذف %1$d رسالة ما من نتائج ما من نتائج - Try a new search. - صوتيات - ملفات - روابط - رسائل صوتية - وسائط + جرّب بحثًا جديدًا. + سيتم عرض الصوتيات من جميع محادثاتك هنا. + سيتم عرض الملفات من جميع محادثاتك هنا. + سيتم عرض الروابط من جميع محادثاتك هنا. + سيتم عرض الرسائل الصوتية من جميع محادثاتك هنا. + سيتم عرض الوسائط من جميع محادثاتك هنا. محادثات + تم تثبيت الرسالة + أُلغي تثبيت الرسالة ترقية إلى مشرف تعديل صلاحيات المشرف @@ -441,7 +444,7 @@ حذف رسائل الآخرين حذف الرسائل إضافة مشرفين جدد - البقاء مجهولًا + البقاء متخفيًا إزالة الإشراف نقل ملكية المجموعة نقل ملكية القناة @@ -473,7 +476,7 @@ إرسال الوسائط إرسال الاستفتاءات إرسال الملصقات والصور المتحركة - تضمين الروابط + معاينة للروابط تغيير معلومات المحادثة تثبيت الرسائل إضافة مستخدمين @@ -482,7 +485,7 @@ لا وسائط لا استفتاءات لا ملصقات وصور متحركة - لا روابط مضمَّنة + بلا معاينة للروابط لا يمكنه تغيير المعلومات لا تثبيت رسائل لا يمكنه إضافة مستخدمين @@ -563,6 +566,7 @@ تم تفعيل الوضع البطيء. لا يمكنك إرسال أكثر من رسالة مرةً واحدة. تم تفعيل الوضع البطيء. لا يمكنك تحديد المزيد من العناصر. المعذرة، هذا النص طويل للغاية ولا يمكن إرساله برسالة واحدة.\n\nتم تفعيل الوضع البطيء. لا يمكنك إرسال عدة رسائل مرةً واحدة. + **%1$s** promoted to admin استفتاء جديد اختبار جديد @@ -703,7 +707,7 @@ تثبيت الرسائل إرسال الاستفتاءات إرسال الرسائل - تضمين الروابط + معاينة الروابط قراءة الرسائل غيّرَ صلاحيات %1$s تغيير معلومات القناة @@ -882,7 +886,7 @@ إضافة %1$s لجهات الاتصال عرض جهة الاتصال هل ترغب بحظر **%1$s** من مراسلتك والاتصال بك على تيليجرام؟ - Do you want to block messages from **%1$s**? + هل ترغب بحظر الرسائل من **%1$s**؟ هل ترغب حقًا في التبليغ عن إزعاج من هذا المستخدم؟ هل ترغب حقًا في التبليغ عن إزعاج من هذه المجموعة؟ هل ترغب حقًا في التبليغ عن إزعاج من هذه القناة؟ @@ -895,10 +899,12 @@ اضغط هنا للوصول للصور المتحركة المحفوظة تثبيت إشعار جميع الأعضاء + Also pin for %1$s إلغاء التثبيت تثبيت الرسالة إلغاء تثبيت الرسالة - هل ترغب في تثبيت هذه الرسالة في هذه المجموعة؟ + Do you want to pin an older message while leaving a more recent one pinned? + هل تريد تثبيت هذه الرسالة لكل الأعضاء في المجموعة؟ هل ترغب في تثبيت هذه الرسالة في هذه القناة؟ هل ترغب في تثبيت هذه الرسالة أعلى هذه المحادثة؟ هل ترغب في إلغاء تثبيت هذه الرسالة؟ @@ -923,6 +929,7 @@ أخرى الوصف رسالة مثبتة + الرسالة السابقة استفتاء مثبت معدلة تعديل الرسالة @@ -970,11 +977,11 @@ قام مشرفو هذه المجموعة بتقييدك من إرسال الملصقات. قام مشرفو هذه المجموعة بتقييدك من إرسال الصور المتحركة إليها. قام مشرفو هذه المجموعة بتقييدك من الكتابة هنا. - لا يُسمحُ بإرسال الوسائط في هذه المجموعة. - لا يُسمحُ بإرسال محتوى استعلامي في هذه المجموعة. - لا يُسمحُ بإرسال الملصقات في هذه المجموعة. - لا يُسمحُ بإرسال الصور المتحركة في هذه المجموعة. - لا يُسمحُ بكتابة الرسائل في هذه المجموعة. + لا يُسمح بإرسال الوسائط في هذه المجموعة. + لا يُسمح بإرسال محتوى استعلامي في هذه المجموعة. + لا يُسمح بإرسال الملصقات في هذه المجموعة. + لا يُسمح بإرسال الصور المتحركة في هذه المجموعة. + لا يُسمح بكتابة الرسائل في هذه المجموعة. مشرف "تثبيت ملفات APK محظور لهذا التطبيق، يمكنك السماح بهذا من إعدادات النظام. " الرسائل غير المقروءة @@ -996,7 +1003,7 @@ انقر لأخذ صورة، اضغط باستمرار لتصوير مقطع مرئي انقر للعرض في قائمة. إرسال بدون صوت - إرسال الآن> + إرسال الآن إعادة جدولة اليوم جدولة @@ -1041,25 +1048,28 @@ د س أس - to private messages and groups - + إلى الرسائل الخاصة والمجموعات نقل ملكية البوت - This will transfer the **full owner** rights for the bot to the selected user. + سيتم نقل **جميع حقوق الملكية** للبوت إلى المستخدم المحدّد. تغيير المالك - You can transfer bot only if you have: + تستطيع نقل البوت فقط إذا: كتابة تعليق - Comments - Comment + التعليقات + تعليق الردود ما من تعليقات هنا بعد... - No replies here yet... + ما من ردود هنا بعد... عرض في المحادثة - إرسال كمجهول + الإرسال متخفيًا بداية المناقشة عرض الموضوع - Choose date + اختيار تاريخ تساعدك هذه المحادثة في تتبع الردود على تعليقاتك في القنوات. - Sorry, this post has been removed from the discussion group. + المعذرة، تمت إزالة هذا المنشور من مجموعة المناقشة. + إلغاء تثبيت كل الرسائل + إخفاء الرسائل المثبّتة + Pinned messages hidden + Pinned messages will be shown again if a new message is pinned. عيّن %1$s عداد التدمير الذاتي ليصبح %2$s قمت بتعيين عداد التدمير الذاتي ليصبح %1$s @@ -1161,7 +1171,7 @@ ثبّتَت %1$s استفتاء %2$s ثبت %1$s الاختبار «%2$s» %1$s ثبت صورة - %1$s ثبت لعبة + ثبّت %1$s لعبة ثبّتَت %1$s نتيجة لعبة ثبت %1$s مقطعًا مرئيًا ثبت %1$s ملفًا @@ -1175,6 +1185,25 @@ ثبت %1$s موقعًا حيًا ثبت %1$s صورةً متحركة ثبت %1$s ملفًا صوتيًا + ثبّت %1$s \"%2$s\" + ثبّت %1$s رسالة + ثبّت %1$s استفتاء %2$s + ثبّت %1$s اختبار %2$s + ثبّت %1$s صورة + ثبّت %1$s لعبة + ثبّت %1$s نتيجة لعبة + ثبّت %1$s مقطعًا مرئيًا + ثبّت %1$s ملفًا + ثبّت %1$s فاتورة + ثبّت %1$s ملصقًا + %1$s pinned a %2$s sticker + ثبّت %1$s رسالة صوتيّة + ثبّت %1$s رسالة مرئية + %1$s pinned a contact %2$s + ثبّت %1$s خريطة + ثبّت %1$s موقعًا مباشرًا + ثبّت %1$s صورة متحركة + ثبّت %1$s ملفًا صوتيًا تيليجرام اختر جهة اتصال @@ -1211,10 +1240,13 @@ مرتبة حسب تاريخ آخر ظهور إضافة %1$s رقم الهاتف - You have no contacts on Telegram yet + ليس لديك جهات اتصال على تيليجرام بعد دعوة الأصدقاء لتجربة تيليجرام - Find people nearby to chat with - Search people by username + اعثر على الأشخاص القريبين للتحدث معهم + البحث عن أشخاص عبر اسم المستخدم + جهة اتصال جديدة + رقم الهاتف **%1$s** ليس في قائمة جهات اتصالك. هل تريد إضافته؟ + إضافة جهة اتصال إضافة أشخاص... ستتمكن من إضافة المزيد من الأعضاء بعد انتهاءك من إنشاء المجموعة. @@ -1422,7 +1454,7 @@ مجدول تلقائي الجدولة - إعدادات النظام الافتراضية + إعدادات النظام استخدام التوقيت المحلي للشروق والغروب تحديث الموقع يتطلب حساب مواعيد الشروق والغروب التحقق لمرة واحدة من موقعك التقريبي. يرجى العلم أن موقعك يتم حفظه في جهازك فقط.\n\nالغروب: %1$s\nالشروق: %2$s @@ -1510,7 +1542,7 @@ أيمن صباح الخير!👋 صباح الخير - طلعت يا محلا نورها يا شمس الشموسة + ماهو الوقت الآن؟ الوقت صباح هنا في *دبي* 😎 استخدام نمط آخر يمكنك أيضًا اختيار أحد الأنماط الحالية كأساس لنمطك الجديد. @@ -1622,7 +1654,7 @@ ماهو الوقت الآن؟ الوقت صباح هنا في دبي 😎 اضغط على «تعيين» لتطبيق الخلفية. - طلعت يا محلا نورها يا شمس الشموسة + استمتع بالخلفية. تعيين كخلفية بحث بواسطة اللون البحث عن خلفيات @@ -2310,6 +2342,12 @@ على بُعد %1$s ك.م على بُعد %1$s قدم على بُعد %1$s ميل + %1$s قدم + %1$s ميل + ميل + كم + %1$s م + %1$s كم يبعد %1$s م عنك يبعد %1$s كم عنك يبعد %1$s ق عنك @@ -2342,7 +2380,9 @@ تم تحديث الموقع %1$s تم تحديثه الآن أنت و%1$s - %1$s يتم مشاركته مع %2$s + %1$s تتم مشاركته مع %2$s + %1$s sharing with %2$s + %1$s sharing with %2$s إيقاف الكل تقوم بمشاركة موقعك الحي مع %1$s اختر المدة التي سيتمكن خلالها %1$s من مشاهدة موقعك الفعلي. @@ -2371,6 +2411,19 @@ تعيين هذا الموقع سيكون بإمكان الناس العثور على مجموعتك في قسم «الأشخاص القريبون». الأماكن في هذه المنطقة + تنبيه الاقتراب + نبّهني عندما يكون %1$s على بعد %2$s + Notify when someone is within %1$s + أنت أقرب من %1$s + مشاركة الموقع + مشاركة + لكي يعمل التنبيه؛ شارك موقعك المباشر في هذه المحادثة. + التنبيه عندما يكون %1$s قريبًا + التنبيه عندما يكون أعضاء المجموعة قريبين + Proximity alert set + We will notify you once %1$s is within %2$s from you. + We will notify you once someone is within %1$s from you. + Proximity alert cancelled عرض في لائحة عرض كمصفوفة @@ -2476,8 +2529,43 @@ المقطع المرئي الأساسي للقناة. صورة العرض الأساسية للمجموعة. المقطع المرئي الأساسي للمجموعة. - Photo saved to gallery - Video saved to gallery + تم حفظ الصورة في المعرض + تم حفظ المقطع المرئي في المعرض + تم حفظ الصورة في التنزيلات + تم حفظ المقطع في التنزيلات + تم حفظ الصورة المتحركة في التنزيلات + File saved to music + File saved to downloads + %1$d files saved to downloads + File saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d photos saved to gallery + Photo saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d videos saved to gallery + Video saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d files saved to music + File saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d items saved to gallery + One item saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery التحقق بخطوتين التحقق بخطوتين @@ -2761,7 +2849,10 @@ عاد un1 للمجموعة انضم un1 للمجموعة لقد عُدتَ للمجموعة - لقد سمحت لهذا البوت بمراسلتك عندما تسجل دخولك إلى %1$s + un1 الآن على بعد %1$s منك + أنت الآن على بعد %1$s من un1 + un1 الآن على بعد %1$s منك un2 + لقد سمحت لهذا البوت بمراسلتك عندما سجّلت دخولك إلى %1$s استلم %1$s الوثائق التالية: %2$s التفاصيل الشخصية العنوان @@ -2917,9 +3008,9 @@ المعذرة، مشرفو هذه المجموعة قيدوك من إرسال الملصقات. المعذرة، قام مشرفو هذه المجموعة بتقييدك من إرسال الوسائط. المعذرة، قام مشرفو هذه المجموعة بتقييدك من إرسال الاستفتاءات. - المعذرة، لا يُسمحُ بإرسال الملصقات في هذه المجموعة. - المعذرة، لا يُسمحُ بإرسال الوسائط في هذه المجموعة. - المعذرة، لا يُسمحُ بإرسال الاستفتاءات في هذه المجموعة. + المعذرة، لا يُسمح بإرسال الملصقات في هذه المجموعة. + المعذرة، لا يُسمح بإرسال الوسائط في هذه المجموعة. + المعذرة، لا يُسمح بإرسال الاستفتاءات في هذه المجموعة. نحن متأسفون للغاية، ولكن هذا يعني أنه لا يمكنك الاشتراك بتيليجرام.\n\nعلى عكس الآخرين، نحن لا نستخدم بياناتك لاستهدافك بالإعلانات أو لأغراض تجارية أخرى. لا يخزن تيليجرام سوى المعلومات التي يحتاجها ليعمل كخدمة سحابية غنية بالميزات. يمكنك ضبط كيفية استخدامنا لبياناتك (مثل إعدادات حذف الجهات المزامَنة) في إعدادات الخصوصية والأمان.\n\nلكن إن كنت غير موافق على احتياجات تيليجرام المتواضعة بشكل عام، فلن يكون من الممكن لنا تقديم هذه الخدمة. التحقق من العمر سياسة الخصوصية وشروط الخدمة @@ -2937,6 +3028,7 @@ يحتاج تيليجرام إلى صلاحية الظهور فوق التطبيقات لتشغيل المقاطع المرئية في وضع (صورة في الصورة). الإعدادات يرجى السماح لتيليجرام بالظهور على شاشة القفل للتمكن من إجراء المكالمات دون مشاكل. + To share your live location in this chat, Telegram needs access to your location all the time, including while the app is in the background.\n\nWe will access your location only for the duration you choose, and you can stop sharing it any time. We won\'t use your location for any purpose other than sharing it in this chat. النّمو المتابِعون @@ -2966,7 +3058,7 @@ %s بيانات أخرى "أعضاء المجموعة " الأعضاء الجدد حسب المصدر - اللغة الأساسية للأعضاء + لغات الأعضاء الرسائل الأحداث الأعضاء @@ -3005,11 +3097,20 @@ %1$d إضافة المشرفون النشطون الأعضاء النشطون - أشهر المضيفين + أنشط المضيفين %s للرسالة الأيام النشطة يقرؤون الرسائل عرض الملف الشخصي + اليوم + يوم أمس + المشاهدات + Public Shares + Private Shares + عرض الإحصائيات + عرض إحصائيات القناة + إحصائيات المنشور + فتح الرسالة تيليجرام سريع @@ -3138,9 +3239,9 @@ رفض معاودة الاتصال الكاميرا - Are you sure you want to call **%1$s**? + هل أنت متأكد من الاتصال بـ**%1$s**؟ مكالمة صوتية - Are you sure you want to video call **%1$s**? + هل أنت متأكد من إجراء مكالمة مرئية مع **%1$s**؟ مكالمة مرئية تتم معاودة الاتصال @@ -3244,15 +3345,21 @@ %1$d رسائل جديدة %1$d رسالة جديدة %1$d رسالة جديدة + %1$d messages unpinned + message unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned %1$d رسالة - الرسالة - الرسالتين + رسالة واحدة + رسالتين %1$d رسائل %1$d رسالة %1$d رسالة - %1$d عنصر + %1$d عنصار عنصر واحد - عنصرَين + عنصران %1$d عناصر %1$d عنصرًا %1$d عنصر @@ -3400,12 +3507,18 @@ %1$s مشاركات %1$s مشاركة %1$s مشاركة - %1$s shared - %1$s shared - %1$s shared - %1$s shared - %1$s shared - %1$s shared + %1$s public shares + %1$s public share + %1$s public shares + %1$s public shares + %1$s public shares + %1$s public shares + %1$s مشاركة + مشاركة واحدة + مشاركتان + %1$s مشاركات + %1$s مشاركة + %1$s مشاركة %1$s حزمة ملصقات حزمة ملصقات واحدة حزمتا ملصقات @@ -3593,24 +3706,42 @@ تم تحديد %1$d من %2$d تم تحديد %1$d من %2$d تم تحديد %1$d من %2$d - View %1$d Replies - View %1$d Reply - View %1$d Replies - View %1$d Replies - View %1$d Replies - View %1$d Replies - %1$d Replies - %1$d Reply - %1$d Replies - %1$d Replies - %1$d Replies - %1$d Replies - %1$d Comments - %1$d Comment - %1$d Comments - %1$d Comments - %1$d Comments - %1$d Comments + عرض %1$d رد + عرض الرد + عرض الرّدين + عرض %1$d ردود + عرض %1$d ردًا + عرض %1$d رد + %1$d ردود + رد + ردان + %1$d ردود + %1$d ردًا + %1$d رد + %1$d تعليق + تعليق + تعليقان + %1$d تعليقات + %1$d تعليقا + %1$d تعليق + %1$d تعليقات + تعليق واحد + تعليقان + %1$d تعليقات + %1$d تعليقًا + %1$d تعليق + تعليقات + تعليق واحد + تعليقان + تعليقات + تعليقًا + تعليق + %1$d Pinned Messages + Pinned Message + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages مجموعة قناة @@ -3684,6 +3815,7 @@ العنوان الرأسية موقعي + التنبيه عندما يكون في النطاق دقة المقطع المرئي الأبعاد أخذ صورة أخرى @@ -3737,6 +3869,7 @@ تم التبديل إلى الكاميرا الخلفية الكاميرا مفتوحة الكاميرا مغلقة + قائمة الرسائل المثبّتة yyyy MMMM MMM dd yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'ذكّرني اليوم عند\' HH:mm \'ذكّرني بتاريخ\' d MMM \'عند\' HH:mm \'ذكّرني بتاريخ\' d MMM yyyy \'عند\' HH:mm - Today diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index a12ea477c..c6eb7c3ea 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -163,7 +163,7 @@ Verstecken Anheften Anheften - Nicht mehr anheften + Loslösen Archivieren Einblenden Archivierte Chats @@ -228,6 +228,7 @@ ZU EINSTELLUNGEN Profil öffnen Kanal öffnen + Gruppe öffnen Nachricht senden Erwähnen Benachrichtigungen stumm @@ -242,12 +243,14 @@ Keine Ergebnisse Keine Ergebnisse Probiere eine neue Suche. - Musik - Dateien - Links - Sprache - Medien + Musik aus all deinen Chats wird hier angezeigt. + Dateien aus all deinen Chats werden hier angezeigt. + Links aus all deinen Chats werden hier angezeigt. + Sprache aus all deinen Chats wird hier angezeigt. + Medien aus all deinen Chats werden hier angezeigt. Chats + Nachricht angeheftet + Nachricht losgelöst Zum Admin machen Adminrechte bearbeiten @@ -563,6 +566,7 @@ Langsamer Modus ist aktiv, du kannst nicht mehr als eine Nachricht gleichzeitig senden. Langsamer Modus ist aktiv, du kannst nicht mehr Elemente auswählen. Dieser Text ist für eine einzelne Nachricht leider zu lang.\n\nLangsamer Modus ist aktiv, du kannst nicht mehr als eine gleichzeitig senden. + **%1$s** als Admin ernannt Neue Umfrage Neues Quiz @@ -895,10 +899,12 @@ Hier tippen um gespeicherte GIFs zu sehen Anheften Mitglieder benachrichtigen + Auch bei %1$s anheften Loslösen Nachricht anheften Nachricht loslösen - Nachricht in der Gruppe wirklich anheften? + Möchtest du eine ältere Nachricht anheften, während du eine neuere Nachricht angeheftet lässt? + Wirklich diese Nachricht in der Gruppe für alle Mitglieder anheften? Nachricht im Kanal wirklich anheften? Möchtest du diese Nachricht ganz oben im Chat anheften? Angeheftete Nachricht wieder entfernen? @@ -923,6 +929,7 @@ Sonstiges Beschreibung Angeheftete Nachricht + Vorherige Nachricht Angeheftete Umfrage bearbeitet Nachricht bearbeiten @@ -996,7 +1003,7 @@ Tippen für Foto, halten für Video Antippen für Listenansicht Ohne Ton senden - Jetzt senden> + Jetzt senden Umplanen Heute Planen @@ -1041,12 +1048,11 @@ m h w - to private messages and groups - - Transfer Bot Ownership + an private Nachrichten und Gruppen + Bot-Inhaberschaft übertragen Das wird die **vollständigen Eigentümerrechte** des Bots an den ausgewählten Nutzer übertragen. Inhaber ändern - You can transfer bot only if you have: + Nur so kannst du einen Bot übertragen: Kommentar hinterlassen Kommentare Kommentar @@ -1059,7 +1065,11 @@ Thread anzeigen Datum wählen Dieser Chat hilft dir, die Antworten auf deine Kommentare in den Kanälen zu verfolgen. - Sorry, this post has been removed from the discussion group. + Dieser Beitrag wurde leider aus der Diskussionsgruppe entfernt. + ALLE NACHRICHTEN LOSLÖSEN + ANGEHEFTETE NACHRICHTEN VERSTECKEN + Angeheftete Nachrichten versteckt + Neu angeheftete Nachrichten lässt sie erneut erscheinen. %1$s hat den Timer auf %2$s gesetzt Du hast den Timer auf %1$s gesetzt @@ -1175,6 +1185,25 @@ %1$s hat einen Live-Standort angeheftet %1$s hat ein GIF angeheftet %1$s hat Audiodatei angeheftet + %1$s hat \"%2$s\" angeheftet + %1$s hat eine Nachricht angeheftet + %1$s hat eine Umfrage angeheftet %2$s + %1$s hat ein Quiz angeheftet %2$s + %1$s hat ein Bild angeheftet + %1$s hat ein Spiel angeheftet + %1$s hat einen Spielstand angeheftet + %1$s hat ein Video angeheftet + %1$s hat eine Datei angeheftet + %1$s hat eine Rechnung angeheftet + %1$s har einen Sticker angeheftet + %1$s hat einen %2$s-Sticker angeheftet + %1$s hat eine Sprachnachricht angeheftet + %1$s hat eine Videonachricht angeheftet + %1$s hat einen Kontakt angeheftet %2$s + %1$s hat einen Standort angeheftet + %1$s hat einen Live-Standort angeheftet + %1$s hat ein GIF angeheftet + %1$s hat eine Audiodatei angeheftet Telegram Kontakt auswählen @@ -1215,6 +1244,9 @@ Freunde zu Telegram einladen Leute in der Nähe zum Chatten finden Leute über Benutzername finden + Neuer Kontakt + Die Nummer **%1$s** ist nicht in deinen Kontakten. Möchtest du sie hinzufügen? + Kontakt hinzufügen Leute hinzufügen... Mehr Mitglieder kannst du hinzufügen, sobald die Gruppe erstellt wurde. @@ -2310,6 +2342,12 @@ %1$s km entfernt %1$s ft entfernt %1$s mi entfernt + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km %1$sm entfernt %1$skm entfernt %1$sft entfernt @@ -2343,6 +2381,8 @@ gerade aktualisiert Du und %1$s %1$s mit %2$s geteilt + %1$s geteilt mit %2$s + %1$s geteilt mit %2$s ALLE BEENDEN Du teilst deinen Live-Standort mit %1$s Wähle, wie lange %1$s deinen Live-Standort sehen darf. @@ -2371,6 +2411,19 @@ Als Standort festlegen Leute werden deine Gruppe im Bereich \'Leute in der Nähe\" finden können. Orte in der Umgebung + Annäherungsalarm + Hinweis, wenn %1$s innerhalb %2$s ist + Hinweis, wenn jemand innerhalb %1$s ist + Du bist bereits näher als %1$s + Standort teilen + Teilen + Damit der Alarm funktioniert, teile bitte deinen Standort in diesem Chat. + Hinweis, wenn %1$s in der Nähe ist + Alarmieren, wenn andere Mitglieder der Gruppe in der Nähe sind. + Annäherungsalarm gesetzt + Wir benachrichtigen dich, sobald %1$s %2$s von Ihnen dir entfernt ist. + Wir benachrichtigen dich, sobald sich jemand %1$s von dir befindet. + Annäherungsalarm aufgehoben Als Liste Als Gitter @@ -2478,6 +2531,41 @@ Das ist jetzt das Hauptvideo der Gruppe. Bild in Galerie gespeichert Video in Galerie gespeichert + Bild in Downloads gespeichert + Video in Downloads gespeichert + GIF in Downloads gespeichert + Datei in Musik gespeichert + Datei in Downloads gespeichert + %1$d Dateien in Downloads gespeichert + Datei in Downloads gespeichert + %1$d Dateien in Downloads gespeichert + %1$d Dateien in Downloads gespeichert + %1$d Dateien in Downloads gespeichert + %1$d Dateien in Downloads gespeichert + %1$d Bilder in Galerie gespeichert + Bild in Galerie gespeichert + %1$d Bilder in Galerie gespeichert + %1$d Bilder in Galerie gespeichert + %1$d Bilder in Galerie gespeichert + %1$d Bilder in Galerie gespeichert + %1$d Videos in Galerie gespeichert + Video in Galerie gespeichert + %1$d Videos in Galerie gespeichert + %1$d Videos in Galerie gespeichert + %1$d Videos in Galerie gespeichert + %1$d Videos in Galerie gespeichert + %1$d Dateien in Musik gespeichert + Datei in Musik gespeichert + %1$d Dateien in Musik gespeichert + %1$d Dateien in Musik gespeichert + %1$d Dateien in Musik gespeichert + %1$d Dateien in Musik gespeichert + %1$d Objekte in Galerie gespeichert + Ein Objekt in Galerie gespeichert + %1$d Objekte in Galerie gespeichert + %1$d Objekte in Galerie gespeichert + %1$d Objekte in Galerie gespeichert + %1$d Objekte in Galerie gespeichert Zweistufige Bestätigung Zweistufige Bestätigung @@ -2761,6 +2849,9 @@ un1 ist in die Gruppe zurückgekehrt un1 ist der Gruppe beigetreten Du bist in die Gruppe zurückgekehrt + un1 ist jetzt %1$s von dir entfernt + Du befindest dich jetzt innerhalb %1$s von un1 + un1 ist jetzt %1$s von un2 entfernt Du hast diesem Bot erlaubt, dich anzuschreiben, als du dich auf %1$s angemeldet hast. %1$s hat die folgenden Dokumente erhalten: %2$s Persönliche Daten @@ -2937,6 +3028,7 @@ Telegram braucht Zugriff auf die Funktion \'Über andere Apps einblenden\'. Nur so können Videos im Bild in Bild Modus wiedergegeben werden. EINSTELLUNGEN Bitte erlaube Telegram auf dem Sperrbildschirm, damit Anrufe signalisiert werden können. + Um deinen Live-Standort in diesem Chat zu teilen, muss Telegram die ganze Zeit Zugang zu deinem Standort haben, auch während die App im Hintergrund läuft.\n\nWir greifen nur für die von dir gewählte Dauer auf deinen Standort zu und du kannst jederzeit aufhören, ihn zu teilen. Wir werden deinen Standort für keinen anderen Zweck nutzen, als ihn in diesem Chat zu teilen. Wachstum Abonnenten @@ -3010,6 +3102,15 @@ Aktivste Wochentage Nachrichten anzeigen Profil öffnen + Heute + Gestern + Aufrufe + Öffentlich geteilt + Privat geteilt + Statistiken anzeigen + Kanal-Statistiken anzeigen + Nachrichtenstatistik + Nachricht öffnen Telegram Schnell @@ -3244,6 +3345,12 @@ %1$d neue Nachrichten %1$d neue Nachrichten %1$d neue Nachrichten + %1$d Nachrichten losgelöst + Nachricht losgelöst + %1$d Nachrichten losgelöst + %1$d Nachrichten losgelöst + %1$d Nachrichten losgelöst + %1$d Nachrichten losgelöst %1$d Nachrichten %1$d Nachricht %1$d Nachrichten @@ -3400,6 +3507,12 @@ %1$sx geteilt %1$sx geteilt %1$sx geteilt + %1$sx öffentlich geteilt + %1$sx öffentlich geteilt + %1$sx öffentlich geteilt + %1$sx öffentlich geteilt + %1$sx öffentlich geteilt + %1$sx öffentlich geteilt %1$s geteilt %1$s geteilt %1$s geteilt @@ -3611,6 +3724,24 @@ %1$d Kommentare %1$d Kommentare %1$d Kommentare + %1$d Kommentare + %1$d Kommentar + %1$d Kommentare + %1$d Kommentare + %1$d Kommentare + %1$d Kommentare + Kommentare + Kommentar + Kommentare + Kommentare + Kommentare + Kommentare + %1$d angeheftete Nachrichten + Angeheftete Nachricht + %1$d angeheftete Nachrichten + %1$d angeheftete Nachrichten + %1$d angeheftete Nachrichten + %1$d angeheftete Nachrichten Gruppe Kanal @@ -3684,6 +3815,7 @@ Titel Überschrift Mein Standort + Benachrichtigen, wenn Leute, die ihren Standort teilen, in der Nähe sind Videoqualität Seitenverhältnis Nimm ein weiteres Bild auf @@ -3737,6 +3869,7 @@ Zur hinteren Kamera gewechselt Kamera ist an Kamera ist aus + Liste angehefteter Nachrichten MMMM yyyy dd. MMM yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'Heute um\' HH:mm \'erinnern\' \'Am\' d MMM \'um\' HH:mm \'erinnern\' \'Am\' d MMM yyyy \'um\' HH:mm \'erinnern\' - Today diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 43e5476c5..7c3ca4f56 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -228,6 +228,7 @@ IR A AJUSTES Abrir perfil Abrir canal + Abrir grupo Enviar mensaje Mencionar Notificaciones silenciadas @@ -242,12 +243,14 @@ Sin resultados Sin resultados Intenta una nueva búsqueda. - Música - Archivos - Enlaces - Voz - Media + La música de todos tus chats aparecerá aquí. + Los archivos de todos tus chats aparecerán aquí. + Los enlaces de todos tus chats aparecerán aquí. + Los mensajes de voz de todos tus chats aparecerán aquí. + La multimedia de todos tus chats aparecerá aquí. Chats + Mensaje fijado + Mensaje desfijado Promover a administrador Permisos de administrador @@ -560,9 +563,10 @@ %1$dh Elige el tiempo que cada miembro debe esperar antes de enviar su siguiente mensaje. Los miembros podrán enviar sólo un mensaje cada %1$s. - El modo lento está activado. No puedes enviar más de un mensaje a la vez. - El modo lento está activado. No puedes seleccionar más ítems. - Lo sentimos, este texto es muy largo para ser enviado en un mensaje.\n\nEl modo lento está activado. No puedes enviar más de un mensaje a la vez. + El modo lento está activo. No puedes enviar más de un mensaje a la vez. + El modo lento está activo. No puedes seleccionar más ítems. + Lo sentimos, este texto es muy largo para ser enviado en un mensaje.\n\nEl modo lento está activo. No puedes enviar más de un mensaje a la vez. + **%1$s** promovido a administrador Nueva encuesta Nuevo cuestionario @@ -895,10 +899,12 @@ Toca y ve los GIF guardados Fijar Notificar a todos los miembros + Fijar también para %1$s Desfijar Fijar mensaje Desfijar mensaje - ¿Quieres fijar este mensaje en el grupo? + ¿Quieres fijar un mensaje más antiguo y a la vez mantener fijado uno más reciente? + ¿Quieres fijar este mensaje para todos los miembros del grupo? ¿Quieres fijar este mensaje en el canal? ¿Quieres fijar este mensaje en la parte de arriba del chat? ¿Quieres desfijar este mensaje? @@ -923,6 +929,7 @@ Otros Descripción Mensaje fijado + Mensaje anterior Encuesta fijada editado Editar mensaje @@ -992,11 +999,11 @@ ESTAFA vía El mensaje no existe - Modo lento activado. Puedes enviar\ntu próximo mensaje en %1$s. + Modo lento activo. Puedes enviar\ntu próximo mensaje en %1$s. Toca para foto, mantén para video Toca para ver como lista. Enviar sin sonido - Enviar ahora> + Enviar ahora Reprogramar Hoy Programar @@ -1042,7 +1049,6 @@ h S a chats privados y grupos - Transferir propiedad del bot Esto transferirá todos los **derechos de propietario** del bot al usuario elegido. Cambiar propietario @@ -1059,7 +1065,11 @@ Ver hilo Elige una fecha Este chat te ayuda a realizar un seguimiento de las respuestas a tus comentarios en canales. - Sorry, this post has been removed from the discussion group. + Esta publicación ha sido eliminada del grupo de conversación. + DESFIJAR TODOS LOS MENSAJES + OCULTAR MENSAJES FIJADOS + Mensajes fijados ocultos + Verás los mensajes fijados\notra vez si se fija uno nuevo. %1$s activó la autodestrucción en %2$s Activaste la autodestrucción en %1$s @@ -1175,6 +1185,25 @@ %1$s fijó una ubicación en tiempo real %1$s fijó un GIF %1$s fijó un audio + %1$s fijó “%2$s” + %1$s fijó un mensaje + %1$s fijó una encuesta %2$s + %1$s fijó un cuestionario %2$s + %1$s fijó una foto + %1$s fijó un juego + %1$s fijó una puntuación + %1$s fijó un video + %1$s fijó un archivo + %1$s fijó una factura + %1$s fijó un sticker + %1$s fijó un %2$s sticker + %1$s fijó un mensaje de voz + %1$s fijó un videomensaje + %1$s fijó un contacto %2$s + %1$s fijó un mapa + %1$s fijó una ubicación en tiempo real + %1$s fijó un GIF + %1$s fijó un audio Telegram Elige un contacto @@ -1215,6 +1244,9 @@ Invita a tus amigos a probar Telegram Encuentra personas cerca para chatear Busca personas por nombre de usuario + Nuevo contacto + El número de teléfono **%1$s** no está en tu lista de contactos. ¿Quieres añadirlo? + Añadir contacto Añadir personas... Podrás añadir más miembros después de crear el grupo. @@ -1662,7 +1694,7 @@ Estás a punto de aplicar un pack de idioma personalizado (**%1$s**) que está completo en un %2$d%%.\n\nEsto traducirá toda la interfaz. Puedes sugerir correcciones en la [plataforma de traducción].\n\nPuedes cambiar el idioma cuando quieras en Ajustes. Datos insuficientes Idiomas no oficiales - Ese idioma no está. + Idioma no disponible. Ya estás usando este pack de idioma (**%1$s**). Puedes cambiar el idioma cuando quieras en Ajustes. Lamentablemente, este pack de idioma personalizado (**%1$s**) no contiene datos para Telegram Android. Ten en cuenta que el soporte de Telegram está hecho por voluntarios. Respondemos lo antes posible, pero puede tomar tiempo.\n\nPor favor, mira las Preguntas frecuentes de Telegram]]>: tienen respuestas para la mayoría de las preguntas y soluciones a problemas]]>. @@ -2310,6 +2342,12 @@ a %1$s km a %1$s ft a %1$s mi + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km a %1$s m de ti a %1$s km de ti a %1$s ft de ti @@ -2334,7 +2372,7 @@ O elige un lugar Toca para enviar esta ubicación Ubicaciones en tiempo real - Ubicación en tiempo real + En tiempo real 15 minutos 1 hora 8 horas @@ -2343,6 +2381,8 @@ recién actualizada Tú y %1$s %1$s compartida con %2$s + %1$s compartida con %2$s + %1$s compartida con %2$s DETENER TODO Compartiendo tu ubicación en tiempo real con %1$s Elige durante cuánto tiempo %1$s verá tu ubicación exacta. @@ -2371,6 +2411,19 @@ Establecer esta ubicación Las personas podrán encontrar tu grupo en la sección “Personas cerca”. Lugares en esta zona + Aviso de proximidad + Notificar cuando %1$s esté a %2$s + Notificar cuando alguien esté a %1$s + Ya estás a menos de %1$s + Compartir ubicación + Compartir + Para que funcione el aviso, por favor, comparte tu ubicación en tiempo real en este chat. + Avisar cuando %1$s esté cerca + Avisar cuando otros miembros del grupo estén cerca + Aviso de proximidad activo + Te notificaremos cuando %1$s esté a %2$s de ti. + We will notify you once someone is within %1$s from you. + Aviso de proximidad cancelado Mostrar como lista Mostrar como cuadrícula @@ -2478,6 +2531,41 @@ Ahora este es el video principal del grupo. Foto guardada en Galería Video guardado en Galería + Foto guardada en descargas + Video guardado en descargas + GIF guardado en descargas + Archivo guardado en música + Archivo guardado en descargas + %1$d archivos guardados en descargas + Archivo guardado en descargas + %1$d archivos guardados en descargas + %1$d archivos guardados en descargas + %1$d archivos guardados en descargas + %1$d archivos guardados en descargas + %1$d fotos guardadas en galería + Foto guardada en galería + %1$d fotos guardadas en galería + %1$d fotos guardadas en galería + %1$d fotos guardadas en galería + %1$d fotos guardadas en galería + %1$d videos guardados en galería + Video guardado en galería + %1$d videos guardados en galería + %1$d videos guardados en galería + %1$d videos guardados en galería + %1$d videos guardados en galería + %1$d archivos guardados en música + Archivo guardado en música + %1$d archivos guardados en música + %1$d archivos guardados en música + %1$d archivos guardados en música + %1$d archivos guardados en música + %1$d ítems guardados en galería + Ítem guardado en galería + %1$d ítems guardados en galería + %1$d ítems guardados en galería + %1$d ítems guardados en galería + %1$d ítems guardados en galería Verificación en dos pasos Verificación en dos pasos @@ -2761,6 +2849,9 @@ un1 volvió al grupo un1 se unió al grupo Volviste al grupo + un1 ahora está a %1$s de ti + Ahora estás a %1$s de un1 + un1 ahora está a %1$s de un2 Autorizaste que este bot te envíe mensajes cuando iniciaste sesión en %1$s. %1$s recibió los siguientes documentos: %2$s Datos personales @@ -2937,6 +3028,7 @@ Telegram necesita acceso a mostrarse sobre otras aplicaciones para usar el modo imagen en imagen. AJUSTES Por favor, permite a Telegram aparecer en la pantalla bloqueada para que las llamadas funcionen correctamente. + Para compartir tu ubicación en tiempo real en este chat, Telegram necesita acceso a tu ubicación todo el tiempo, incluyendo cuando la app está en segundo plano.\n\nAccederemos a tu ubicación sólo durante el tiempo que elijas, y puedes dejar de compartirla en cualquier momento. No usaremos tu ubicación para ningún otro propósito que no sea el de compartirla en este chat. Crecimiento Seguidores @@ -2957,7 +3049,7 @@ Borrar caché de Telegram Resumen Vistas por post - Comparticiones por post + Reenvíos por post Notificaciones activas Borrar base de datos local "Caché de Telegram • %s " @@ -3010,6 +3102,15 @@ Top días de la semana Ver mensajes Abrir perfil + Hoy + Ayer + Vistas + Reenvíos en público + Reenvíos en privado + Ver estadísticas + Ver estadísticas del canal + Estadísticas del mensaje + Abrir mensaje Telegram Rápida @@ -3244,6 +3345,12 @@ %1$d mensajes nuevos %1$d mensajes nuevos %1$d mensajes nuevos + %1$d mensajes desfijados + mensaje desfijado + %1$d mensajes desfijados + %1$d mensajes desfijados + %1$d mensajes desfijados + %1$d mensajes desfijados %1$d mensajes %1$d mensaje %1$d mensajes @@ -3400,6 +3507,12 @@ %1$s reenvíos %1$s reenvíos %1$s reenvíos + %1$s reenvíos públicos + %1$s reenvío público + %1$s reenvíos públicos + %1$s reenvíos públicos + %1$s reenvíos públicos + %1$s reenvíos públicos %1$s reenvíos %1$s reenvío %1$s reenvíos @@ -3611,6 +3724,24 @@ %1$d comentarios %1$d comentarios %1$d comentarios + %1$d comentarios + %1$d comentario + %1$d comentarios + %1$d comentarios + %1$d comentarios + %1$d comentarios + comentarios + comentario + comentarios + comentarios + comentarios + comentarios + %1$d mensajes fijados + Mensaje fijado + %1$d mensajes fijados + %1$d mensajes fijados + %1$d mensajes fijados + %1$d mensajes fijados Grupo Canal @@ -3684,6 +3815,7 @@ Título Encabezado Mi ubicación + Notificar cuando las personas que comparten su ubicación estén dentro del rango Calidad de video Relación de aspecto Tomar una foto más @@ -3737,6 +3869,7 @@ Cambió a la cámara trasera La cámara está encendida La cámara está apagada + Lista de mensajes fijados MMMM \'de\' yyyy dd MMM yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'Recordar hoy a las\' HH:mm \'Recordar el\' d \'de\' MMM \'a las\' HH:mm \'Recordar el\' d \'de\' MMM \'de\' yyyy \'a las\' HH:mm - Today diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 7de6b8e48..3e8e66a12 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -228,6 +228,7 @@ VAI ALLE IMPOSTAZIONI Apri profilo Apri canale + Apri gruppo Invia messaggio Menziona Notifiche silenziate @@ -242,12 +243,14 @@ Nessun risultato Nessun risultato Prova una nuova ricerca. - Musica - File - Link - Vocali - Media + La musica da tutte le tue chat apparirà qui. + I file da tutte le tue chat appariranno qui. + I link da tutte le tue chat appariranno qui. + I vocali da tutte le tue chat appariranno qui. + I media da tutte le tue chat appariranno qui. Chat + Messaggio fissato + Messaggio tolto Rendi amministratore Modifica permessi amministratore @@ -283,7 +286,7 @@ un1 ha fissato un contatto un1 ha fissato %1$s un1 ha fissato una posizione - un1 ha fissato una posizione attuale + un1 ha fissato una posizione in tempo reale un1 ha fissato una GIF un1 ha fissato un file audio Questo gruppo è stato aggiornato a supergruppo @@ -413,7 +416,7 @@ %1$s ha pubblicato un sondaggio %2$s %1$s ha pubblicato il quiz \"%2$s\" %1$s ha pubblicato una posizione - %1$s ha pubblicato una posizione attuale + %1$s ha pubblicato una posizione in tempo reale %1$s ha pubblicato un file %1$s ha pubblicato una GIF %1$s ha pubblicato %2$s @@ -441,7 +444,7 @@ Eliminare messaggi altrui Eliminare messaggi Aggiungere amministratori - Invia anonimamente + Inviare anonimamente Rimuovi amministratore Trasferisci proprietà gruppo Trasferisci proprietà canale @@ -558,11 +561,12 @@ %1$ds %1$dm %1$dh - Scegli quanto tempo ciascun membro deve attendere prima di inviare il messaggio successivo. + Scegli quanto dovranno aspettare i membri prima di inviare il messaggio successivo. I membri potranno inviare solo un messaggio ogni %1$s. La modalità lenta è attiva. Non puoi inviare più di un messaggio alla volta. La modalità lenta è attiva. Non puoi selezionare più elementi. Spiacenti, questo testo è troppo lungo da inviare come singolo messaggio.\n\nLa modalità lenta è attiva. Non puoi inviare più di un messaggio alla volta. + **%1$s** promosso ad amministratore Nuovo sondaggio Nuovo quiz @@ -796,11 +800,11 @@ %1$s sta inviando un audio... %1$s sta inviando una foto... APERTURA RAPIDA - APRI GRUPPO + VISUALIZZA GRUPPO VISUALIZZA SFONDO VISUALIZZA TEMA - APRI CANALE - APRI MESSAGGIO + VISUALIZZA CANALE + VISUALIZZA MESSAGGIO Il tema scuro si attiverà automaticamente durante la notte Note %1$s sta giocando a un gioco... @@ -895,10 +899,12 @@ Tocca qui per vedere le GIF salvate Fissa Notifica tutti i membri + Fissa anche per %1$s Togli Fissa messaggio Togli messaggio - Vuoi fissare questo messaggio in questo gruppo? + Vuoi fissare un vecchio messaggio lasciandone fissato uno più recente? + Vuoi fissare questo messaggio per tutti i membri del gruppo? Vuoi fissare questo messaggio in questo canale? Vuoi fissare questo messaggio nella parte superiore della chat? Vuoi togliere questo messaggio? @@ -923,6 +929,7 @@ Altro Descrizione Messaggio fissato + Messaggio precedente Sondaggio fissato modificato Modifica messaggio @@ -956,9 +963,9 @@ Tieni premuto per l\'audio. Tocca per il video. Tieni premuto per il video. Tocca per l\'audio. Scarta messaggio vocale - Sei sicuro di voler arrestare la registrazione e scartare il tuo messaggio vocale? + Sei sicuro di voler terminare la registrazione e scartare il tuo messaggio vocale? Scarta videomessaggio - Sei sicuro di voler arrestare la registrazione e scartare il tuo videomessaggio? + Sei sicuro di voler terminare la registrazione e scartare il tuo videomessaggio? Scarta Gli amministratori di questo gruppo ti hanno vietato di inviare media qui fino al %1$s Gli amministratori di questo gruppo ti hanno vietato di inviare contenuti inline qui fino al %1$s @@ -982,8 +989,8 @@ Cerca sticker in primo piano Cerca emoji URL - Fornitore anteprima mappa - Fornitore anteprima mappa + Anteprima mappa + Anteprima mappa Telegram Google Yandex @@ -996,7 +1003,7 @@ Tocca per le foto, tieni premuto per i video Tocca per vedere come lista. Invia senza suono - Invia ora> + Invia ora Riprogramma Oggi Programma @@ -1041,8 +1048,7 @@ m h S - to private messages and groups - + in chat e gruppi privati Trasferisci proprietà bot Questo trasferirà tutti i **diritti di proprietà** per il bot all\'utente selezionato. Cambia proprietario @@ -1059,7 +1065,11 @@ Visualizza thread Scegli data Questa chat ti aiuta a tenere traccia delle risposte ai tuoi commenti nei canali. - Sorry, this post has been removed from the discussion group. + Spiacenti, questo post è stato rimosso dal gruppo di discussione. + TOGLI TUTTI I MESSAGGI + NASCONDI I MESSAGGI FISSATI + Messaggi fissati nascosti + Rivedrai i messaggi fissati solo se ne sarà fissato uno nuovo. %1$s ha impostato il timer di autodistruzione a %2$s Hai impostato il timer di autodistruzione a %1$s @@ -1082,7 +1092,7 @@ %1$s ti ha inviato un sondaggio %2$s %1$s ti ha inviato il quiz \"%2$s\" %1$s ti ha inviato una posizione - %1$s ti ha inviato una posizione attuale + %1$s ti ha inviato una posizione in tempo reale %1$s ti ha invitato a giocare %2$s %1$s ha totalizzato %3$s a %2$s %1$s ti ha inviato un file @@ -1100,7 +1110,7 @@ %1$s ha inviato il quiz \"%3$s\" nel gruppo %2$s %1$s ha condiviso un contatto %3$s nel gruppo %2$s %1$s ha inviato una posizione nel gruppo %2$s - %1$s ha condiviso una posizione attuale nel gruppo %2$s + %1$s ha condiviso una posizione in tempo reale nel gruppo %2$s %1$s ha invitato il gruppo %2$s a giocare %3$s %1$s ha totalizzato %4$s a %3$s nel gruppo %2$s %1$s ha inviato un file nel gruppo %2$s @@ -1152,7 +1162,7 @@ %1$s ha fissato un videomessaggio nel gruppo %2$s %1$s ha fissato un contatto %3$s nel gruppo %2$s %1$s ha fissato una posizione nel gruppo %2$s - %1$s ha fissato una posizione attuale nel gruppo %2$s + %1$s ha fissato una posizione in tempo reale nel gruppo %2$s %1$s ha fissato una GIF nel gruppo %2$s %1$s ha fissato un file audio nel gruppo %2$s %1$s ha fissato una fattura nel gruppo %2$s @@ -1172,9 +1182,28 @@ %1$s ha fissato un videomessaggio %1$s ha fissato un contatto %2$s %1$s ha fissato una posizione - %1$s ha fissato una posizione attuale + %1$s ha fissato una posizione in tempo reale %1$s ha fissato una GIF %1$s ha fissato un file audio + %1$s ha fissato \"%2$s\" + %1$s ha fissato un messaggio + %1$s ha fissato un sondaggio %2$s + %1$s ha fissato un quiz %2$s + %1$s ha fissato una foto + %1$s ha fissato un gioco + %1$s ha fissato un punteggio + %1$s ha fissato un video + %1$s ha fissato un file + %1$s ha fissato una fattura + %1$s ha fissato uno sticker + %1$s ha fissato uno %2$s sticker + %1$s ha fissato un messaggio vocale + %1$s ha fissato un videomessaggio + %1$s ha fissato un contatto %2$s + %1$s ha fissato una mappa + %1$s ha fissato una posizione in tempo reale + %1$s ha fissato una GIF + %1$s ha fissato un file audio Telegram Seleziona contatto @@ -1215,6 +1244,9 @@ Invita gli amici a provare Telegram Trova persone nelle vicinanze con cui messaggiare Cerca persone tramite username + Nuovo contatto + Il numero di telefono **%1$s** non è tra i tuoi contatti. Vuoi aggiungerlo? + Aggiungi contatto Aggiungi persone... Potrai aggiungere altri membri dopo aver creato il gruppo. @@ -2310,6 +2342,12 @@ distante %1$s km distante %1$s piedi distante %1$s miglia + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km %1$s m da te %1$s km da te %1$s ft da te @@ -2317,15 +2355,15 @@ Indicazioni Nessun luogo trovato Non ci sono risultati per **%1$s** vicino a te. - Invia la mia posizione corrente - Condividi posizione attuale per... - Condividi posizione attuale + Invia la mia posizione attuale + Posizione in tempo reale... + Invia posizione in tempo reale Termina condivisione Termina condivisione posizione - Vuoi interrompere la condivisione della tua posizione attuale con **%1$s**? - Vuoi interrompere la condivisione della tua posizione attuale con **%1$s**? - Vuoi interrompere la condivisione della tua posizione attuale? - Aggiornata in tempo reale + Vuoi terminare la condivisione della posizione in tempo reale con **%1$s**? + Vuoi terminare la condivisione della posizione in tempo reale con **%1$s**? + Vuoi terminare la condivisione della posizione in tempo reale? + Aggiornata mentre ti muovi Invia la posizione selezionata Posizione Luogo @@ -2333,8 +2371,8 @@ distante %1$s O scegli un luogo Tocca per inviare questa posizione - Posizioni attuali - Posizione attuale + Posizioni in tempo reale + Posizione in tempo reale per 15 minuti per 1 ora per 8 ore @@ -2343,10 +2381,12 @@ aggiornata adesso Tu e %1$s %1$s condivisa con %2$s - ARRESTA TUTTO - Stai condividendo la tua posizione attuale in %1$s - Scegli per quanto tempo %1$s vedrà la tua posizione precisa. - Scegli per quanto tempo le persone in questa chat vedranno la tua posizione attuale. + %1$s condivisa con %2$s + %1$s condivisa con %2$s + TERMINA TUTTO + Posizione in tempo reale condivisa con %1$s + Scegli per quanto %1$s vedrà la tua posizione precisa. + Scegli per quanto le persone in questa chat vedranno la tua posizione in tempo reale. Attiva GPS Per favore attiva il tuo GPS per accedere alle funzioni basate sulla posizione. Rendimi visibile @@ -2371,6 +2411,19 @@ Imposta questa posizione Le persone potranno trovare il tuo gruppo nella sezione \"Persone vicine\". Luoghi in quest\'area + Notifica di prossimità + Notifica quando %1$s è a %2$s + Notifica quando qualcuno è a %1$s + Sei già più vicino di %1$s + Condividi posizione + Condividi + Per far funzionare l\'avviso, condividi la posizione in tempo reale in questa chat. + Avvisa quando %1$s è vicino + Avvisa quando gli altri membri del gruppo sono vicini + Notifica di prossimità impostata + Ti notificheremo quando %1$s sarà a %2$s da te. + Ti notificheremo quando qualcuno sarà a %1$s da te. + Notifica di prossimità annullata Mostra come lista Mostra come griglia @@ -2478,6 +2531,41 @@ Questo è ora il video principale del gruppo. Foto salvata nella galleria Video salvato nella galleria + Foto salvata nei download + Video salvato nei download + GIF salvata nei download + File salvato nella musica + File salvato nei download + %1$d file salvati nei download + File salvato nei download + %1$d file salvati nei download + %1$d file salvati nei download + %1$d file salvati nei download + %1$d file salvati nei download + %1$d foto salvate nella galleria + Foto salvata nella galleria + %1$d foto salvate nella galleria + %1$d foto salvate nella galleria + %1$d foto salvate nella galleria + %1$d foto salvate nella galleria + %1$d video salvati nella galleria + Video salvato nella galleria + %1$d video salvati nella galleria + %1$d video salvati nella galleria + %1$d video salvati nella galleria + %1$d video salvati nella galleria + %1$d file salvati nella musica + File salvato nella musica + %1$d file salvati nella musica + %1$d file salvati nella musica + %1$d file salvati nella musica + %1$d file salvati nella musica + %1$d oggetti salvati nella galleria + Un oggetto salvato nella galleria + %1$d oggetti salvati nella galleria + %1$d oggetti salvati nella galleria + %1$d oggetti salvati nella galleria + %1$d oggetti salvati nella galleria Verifica in due passaggi Verifica in due passaggi @@ -2761,6 +2849,9 @@ un1 è tornato nel gruppo un1 si è unito al gruppo Sei tornato nel gruppo + un1 ora è a %1$s da te + Ora sei a %1$s da un1 + un1 ora è a %1$s da un2 Hai permesso a questo bot di scriverti quando ti sei collegato su %1$s. %1$s ha ricevuto i seguenti documenti: %2$s Dettagli personali @@ -2785,7 +2876,7 @@ Il video è scaduto GIF Posizione - Posizione attuale + Posizione in tempo reale Contatto File Sticker @@ -2810,7 +2901,7 @@ Attenzione! Questo **eliminerà tutti i messaggi** in questa chat per **entrambi** i partecipanti. Attenzione! Questo **eliminerà tutti i messaggi** in questa chat. Elimina tutto - Arrestare il caricamento? + Terminare il caricamento? Aggiorna Telegram Spiacenti, la tua app Telegram è obsoleta e non può gestire la richiesta. Per favore aggiorna Telegram. Numero di telefono non valido. Per favore controlla il numero e riprova. @@ -2860,8 +2951,8 @@ Elimina le bozze cloud Sei sicuro di voler eliminare tutte le bozze? Condividere la tua posizione? - Questo invierà la tua posizione corrente al bot. - L\'app non è riuscita a determinare la tua posizione corrente + Questo invierà la tua posizione attuale al bot. + L\'app non è riuscita a determinare la tua posizione attuale Scegli manualmente Questo bot vorrebbe sapere la tua posizione ogni volta che invii una richiesta. Questo può essere usato per fornire risultati specifici in base alla posizione. Condividere il tuo numero di telefono? @@ -2874,7 +2965,7 @@ Chat segreta Sei sicuro di voler iniziare una chat segreta? Sei sicuro di voler annullare la registrazione? - Vuoi arrestare il processo di verifica? + Vuoi terminare il processo di verifica? Sei sicuro di voler eliminare la tua cronologia della chat con **%1$s**? Sei sicuro di voler eliminare la tua cronologia della chat segreta con **%1$s**? Sei sicuro di voler cancellare la cronologia chat di **%1$s**? @@ -2937,6 +3028,7 @@ Telegram deve accedere allo spostamento su altre app per riprodurre i video in modalità PiP. IMPOSTAZIONI Per favore consenti a Telegram di essere visualizzato sulla schermata di blocco in modo che le chiamate possano funzionare correttamente. + Per condividere la posizione in tempo reale in questa chat, Telegram ha bisogno di accedere alla tua posizione in qualsiasi momento, anche quando l\'applicazione è in background.\n\nAccederemo alla tua posizione solo per la durata da te scelta, e potrai smettere di condividerla in qualsiasi momento. Non useremo la tua posizione per nessun altro scopo se non quello di condividerla in questa chat. Crescita Follower @@ -3010,6 +3102,15 @@ Giorni migliori della settimana Visualizza messaggi Apri profilo + Oggi + Ieri + Visualizzazioni + Condivisioni pubbliche + Condivisioni private + Visualizza statistiche + Visualizza statistiche canale + Statistiche messaggio + Apri messaggio Telegram Veloce @@ -3026,7 +3127,7 @@ Inizia a messaggiare Impostazioni account - Usa meno dati per le chiamate + Usa meno dati per chiamare Chiamata in entrata Connetto Scambio chiavi di crittografia @@ -3078,7 +3179,7 @@ L\'app di **%1$s** sta usando un protocollo non compatibile. Deve aggiornare la sua app prima che tu possa chiamarlo. L\'app di **%1$s** non supporta le chiamate. Deve aggiornare la sua app prima che tu possa chiamarlo. Spiacenti, **%1$s** sta usando una vecchia versione di Telegram che non supporta le videochiamate. - Fai una chiamata vocale + Chiamata vocale Per favore valuta la qualità della tua chiamata Telegram Telegram deve accedere al microfono affinché tu possa effettuare chiamate. Telegram deve accedere al tuo microfono e alla tua videocamera affinché tu possa effettuare videochiamate. @@ -3244,6 +3345,12 @@ %1$d nuovi messaggi %1$d nuovi messaggi %1$d nuovi messaggi + %1$d messaggi tolti + messaggio tolto + %1$d messaggi tolti + %1$d messaggi tolti + %1$d messaggi tolti + %1$d messaggi tolti %1$d messaggi %1$d messaggio %1$d messaggi @@ -3400,12 +3507,18 @@ %1$s condivisioni %1$s condivisioni %1$s condivisioni - %1$s shared - %1$s shared - %1$s shared - %1$s shared - %1$s shared - %1$s shared + %1$s condivisioni pubbliche + %1$s condivisione pubblica + %1$s condivisioni pubbliche + %1$s condivisioni pubbliche + %1$s condivisioni pubbliche + %1$s condivisioni pubbliche + %1$s hanno condiviso + %1$s ha condiviso + %1$s hanno condiviso + %1$s hanno condiviso + %1$s hanno condiviso + %1$s hanno condiviso %1$s set di sticker %1$s set di sticker %1$s set di sticker @@ -3611,6 +3724,24 @@ %1$d commenti %1$d commenti %1$d commenti + %1$d commenti + %1$d commento + %1$d commenti + %1$d commenti + %1$d commenti + %1$d commenti + commenti + commento + commenti + commenti + commenti + commenti + %1$d messaggi fissati + Messaggio fissato + %1$d messaggi fissati + %1$d messaggi fissati + %1$d messaggi fissati + %1$d messaggi fissati Gruppo Canale @@ -3660,7 +3791,7 @@ Ripeti, una Chiudi lettore musicale Riproduzione a velocità doppia - Termina condivisione posizione attuale + Termina condivisione posizione in tempo reale Fotocamera istantanea Pulsante di scatto Cambia fotocamera @@ -3684,6 +3815,7 @@ Titolo Titolo La mia posizione + Notifica quando le persone che condividono la posizione sono nelle vicinanze Qualità video Proporzioni Scatta un\'altra foto @@ -3737,6 +3869,7 @@ Passato a videocamera posteriore La videocamera è accesa La videocamera è spenta + Elenco messaggi fissati MMMM yyyy dd MMM yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'Ricorda oggi alle\' HH:mm \'Ricorda il\' d MMM \'alle\' HH:mm \'Ricorda il\' d MMM yyyy \'alle\' HH:mm - Today diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 73500107e..4cecefcc5 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -181,7 +181,7 @@ %1$s 동안 끄기 알림 끄기 %1$s 뒤 - 사용 안 함 + 영원히 음소거 해시태그 최근 사람들 @@ -226,28 +226,31 @@ 새로운 대화방을 숨길까요? 연락처 목록에 없는 사용자에게서 새로운 메시지를 많이 받고 계십니다. 해당 대화방에 **자동 알림 끄기**와 **보관**을 적용하시겠습니까? 설정으로 이동 - Open Profile + 프로필 열기 Open Channel - Send Message - Mention + Open Group + 메시지 보내기 + 언급 Notifications muted Notifications muted for %1$s Notifications unmuted - %1$d messages deleted - Message deleted - %1$d messages deleted - %1$d messages deleted - %1$d messages deleted - %1$d messages deleted + 메시지 %1$d 개가 삭제가 되었습니다. + 메시지 %1$d 개가 삭제가 되었습니다. + 메시지 %1$d 개가 삭제가 되었습니다. + 메시지 %1$d 개가 삭제가 되었습니다. + 메시지 %1$d 개가 삭제가 되었습니다. + 메시지 %1$d 개가 삭제가 되었습니다. No Results - No Results - Try a new search. + 결과 없음 + 검색을 다시 해보세요. Music from all your chats will be shown here. Files from all your chats will be shown here. Links from all your chats will be shown here. Voice from all your chats will be shown here. Media from all your chats will be shown here. - Chats + 대화방 + Message pinned + Message unpinned 관리자로 승격 관리자 권한 수정 @@ -441,7 +444,7 @@ 다른 사람의 메시지 삭제 메시지 삭제 새로운 관리자 추가 - Send Anonymously + 익명으로 보내기 관리자 권한 회수 그룹 소유권 넘기기 채널 소유권 넘기기 @@ -532,9 +535,9 @@ 관리자 세우기 %1$s 님을 제한하시면 이 사용자가 관리자에서 제명됩니다. 토론 - View discussion + 토론 보기 논평을 나눌 그룹 대화방을 추가하세요. - 이어진 채널 + 연결된 채널 Select a group chat that will host comments from your channel. 채널에 게시하시는 모든 것이 이 그룹으로 전달됩니다. **%1$s** is selected as the group that hosts comments for your channel. @@ -563,6 +566,7 @@ 저속 모드가 켜져 있습니다. 한 번에 메시지를 하나 이상 보내실 수 없습니다. 저속 모드가 켜져 있습니다. 항목을 더 선택하실 수 없습니다. 죄송합니다. 이 글은 한 메시지로 치기에 너무 깁니다.\n\n저속 모드가 켜져 있습니다. 한 번에 메시지를 하나 이상 보내실 수 없습니다. + **%1$s** promoted to admin 새로운 설문 새로운 퀴즈 @@ -712,7 +716,7 @@ 메시지 수정 메시지 삭제 관리자 추가 - Send anonymously + 익명으로 보내기 사용자 차단 사용자 추가 제목: %1$s @@ -895,10 +899,12 @@ 저장한 GIF 파일을 보려면 탭하세요. 고정 모든 참가자에게 알리기 + Also pin for %1$s 고정 해제 메시지 고정 메시지 고정 해제 - 그룹에 이 메시지를 고정하시겠습니까? + Do you want to pin an older message while leaving a more recent one pinned? + 그룹에 있는 모든 참가자들에게 이 메시지를 고정하시겠습니까? 채널에 이 메시지를 고정하시겠습니까? 이 메시지를 대화방 위쪽에 고정하시겠습니까? 메시지를 고정 해제하시겠습니까? @@ -923,6 +929,7 @@ 기타 안내 고정된 메시지 + Previous Message 고정된 설문 수정됨 메시지 수정 @@ -996,7 +1003,7 @@ 사진은 짧게, 동영상은 길게 누르세요 목록으로 보려면 누르세요. 소리 없이 보내기 - 지금 보내기> + 지금 보내기 시간 조정하기 오늘 예약 @@ -1042,24 +1049,27 @@ h w to private messages and groups - Transfer Bot Ownership This will transfer the **full owner** rights for the bot to the selected user. Change Owner You can transfer bot only if you have: - Leave a comment - Comments - Comment - Replies - No comments here yet... + 코멘트 남기기 + 코멘트 + 코멘트 보내기 + 답변 + 아직 코멘트가 없습니다... No replies here yet... - View in chat - Send anonymously - Discussion started - View Thread + 대화에서 보기 + 익명으로 보내기 + 토론이 시작되었습니다 + 쓰레드 보기 Choose date This chat helps you keep track of replies to your comments in Channels. Sorry, this post has been removed from the discussion group. + UNPIN ALL MESSAGES + HIDE PINNED MESSAGES + Pinned messages hidden + Pinned messages will be shown again if a new message is pinned. %1$s 님이 자동 삭제 타이머를 %2$s(으)로 맞췄습니다 자동 삭제 타이머를 %1$s(으)로 맞추셨습니다 @@ -1175,6 +1185,25 @@ %1$s 님이 실시간 위치를 고정했습니다 %1$s 님이 GIF를 고정했습니다 %1$s 님이 오디오 파일을 고정했습니다 + %1$s pinned \"%2$s\" + %1$s pinned a message + %1$s pinned a poll %2$s + %1$s pinned a quiz %2$s + %1$s pinned a photo + %1$s pinned a game + %1$s pinned a game score + %1$s pinned a video + %1$s pinned a file + %1$s pinned an invoice + %1$s pinned a sticker + %1$s pinned a %2$s sticker + %1$s pinned a voice message + %1$s pinned a video message + %1$s pinned a contact %2$s + %1$s pinned a map + %1$s pinned a live location + %1$s pinned a GIF + %1$s pinned an audio file 텔레그램 연락처 선택 @@ -1215,6 +1244,9 @@ Invite friends to try Telegram Find people nearby to chat with Search people by username + New contact + The phone number **%1$s** is not in your contact list. Do you want to add it? + Add contact 사람들을 추가하세요... 그룹을 만들고 나서 참가자를 더 추가하실 수 있습니다. @@ -1223,7 +1255,7 @@ 최대 %1$s 죄송합니다. 이 그룹은 이미 가득 찼습니다. 죄송하지만, 대화방이 없어진 모양입니다. - This channel is private. Please join it to continue viewing its content. + 비공개 채널입니다. 대화 내용을 이어 보려면 채널에 들어가 주세요. This group is private. Please join it to continue viewing its content. 채널 들어가기 그룹 들어가기 @@ -2232,13 +2264,13 @@ 읽지 않음 폴더에 추가 폴더에서 제거 - Choose a folder - **%1$s** added to **%2$s** - **%1$s** added to **%2$s** - **%1$s** added to **%2$s** + 폴더를 선택해주세요 + **%2$s** 폴더에 **%1$s** 대화가 추가됨 + **%2$s** 폴더에 **%1$s** 대화가 추가됨 + **%2$s** 폴더에 **%1$s** 대화가 추가됨 **%1$s**을(를) **%2$s**에서 제거했습니다 - **%1$s** removed from **%2$s** - **%1$s** removed from **%2$s** + **%2$s** 폴더에서 **%1$s** 대화가 삭제됨 + **%2$s** 폴더에서 **%1$s** 대화가 삭제됨 Limit reached Sorry, you can\'t add more than 100 chats to a folder. Sorry, you can\'t exclude more than 100 chats from a folder. @@ -2310,6 +2342,12 @@ %1$s km 떨어짐 %1$s ft 떨어짐 %1$s mi 떨어짐 + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km 나에게서 %1$s m 떨어짐 나에게서 %1$s km 떨어짐 나에게서 %1$s ft 떨어짐 @@ -2343,6 +2381,8 @@ 방금 업데이트됨 나와 %1$s 님 %1$s를 %2$s와 공유 중 + %1$s sharing with %2$s + %1$s sharing with %2$s 모두 중단 실시간 위치를 %1$s와 공유하고 있습니다 %1$s 님에게 회원님의 정확한 위치를 얼마 동안 보일지 선택하세요. @@ -2371,6 +2411,19 @@ 이 위치로 설정하기 사람들이 회원님의 그룹을 \"주변 사람\" 섹션에서 찾을 수 있습니다. 지역에 있는 장소 + Proximity alert + Notify when %1$s is within %2$s + Notify when someone is within %1$s + You are already closer than %1$s + Share Location + Share + For the alert to work, please share your live location in this chat. + Alert when %1$s is close + Alert when other members of the group are close + Proximity alert set + We will notify you once %1$s is within %2$s from you. + We will notify you once someone is within %1$s from you. + Proximity alert cancelled 목록으로 보기 그리드로 보기 @@ -2474,10 +2527,45 @@ 앞으로 이것이 회원님의 메인 프로필 동영상입니다. This is the main channel photo now. This is the main channel video now. - This is the main group photo now. - This is the main group video now. + 현재 그룹 대표 사진입니다. + 현재 그룹 대표 영상입니다. Photo saved to gallery Video saved to gallery + Photo saved to downloads + Video saved to downloads + GIF saved to downloads + File saved to music + File saved to downloads + %1$d files saved to downloads + File saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d photos saved to gallery + Photo saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d videos saved to gallery + Video saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d files saved to music + File saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d items saved to gallery + One item saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery 2단계 인증 2단계 인증 @@ -2761,6 +2849,9 @@ un1 님이 그룹에 돌아왔습니다 un1 님이 그룹에 들어왔습니다 그룹에 돌아오셨습니다 + un1 is now within %1$s from you + You are now within %1$s from un1 + un1 is now within %1$s from un2 %1$s에 로그인할 때 이 봇이 회원님에게 메시지를 보내도록 허용하셨습니다. %1$s 님이 다음 서류를 받았습니다: %2$s 개인 신상 명세 @@ -2937,6 +3028,7 @@ 화면속화면 모드로 동영상을 재생하려면 텔레그램에게 다른 앱 위에 그릴 수 있는 권한을 부여하셔야 합니다. 설정 통화가 제대로 실행되도록 텔레그램이 잠금 화면에 나타나는 것을 허용해 주세요. + To share your live location in this chat, Telegram needs access to your location all the time, including while the app is in the background.\n\nWe will access your location only for the duration you choose, and you can stop sharing it any time. We won\'t use your location for any purpose other than sharing it in this chat. 성장 팔로워 @@ -2966,50 +3058,59 @@ %s 기타 데이터 Group members New members by source - Members\' primary language + 참가자 주요 언어 Messages Actions - Members - Messages - Viewing Members - Posting Members - %1$d characters - %1$d character - %1$d characters - %1$d characters - %1$d characters - %1$d characters - %1$d deletions - %1$d deletion - %1$d deletions - %1$d deletions - %1$d deletions - %1$d deletions + 참가자 + 메시지 + 읽기 위주 참가자 + 게시 위주 참가자 + %1$d 자 + %1$d 자 + %1$d 자 + %1$d 자 + %1$d 자 + %1$d 자 + 삭제 %1$d건 + 삭제 %1$d건 + 삭제 %1$d건 + 삭제 %1$d건 + 삭제 %1$d건 + 삭제 %1$d건 %1$d bans %1$d ban %1$d bans %1$d bans %1$d bans %1$d bans - %1$d restrictions - %1$d restriction - %1$d restrictions - %1$d restrictions - %1$d restrictions - %1$d restrictions - %1$d invitations - %1$d invitation - %1$d invitations - %1$d invitations - %1$d invitations - %1$d invitations - Top admins - Top members - Top inviters - %s per message + 제한 %1$d 건 + 제한 %1$d 건 + 제한 %1$d 건 + 제한 %1$d 건 + 제한 %1$d 건 + 제한 %1$d 건 + 초대 %1$d건 + 초대 %1$d건 + 초대 %1$d건 + 초대 %1$d건 + 초대 %1$d건 + 초대 %1$d건 + 상위 관리자 + 상위 참가자 + 상위 초대자 + 메시지 당 %s자 Top days of week - View Messages - Open Profile + 메시지 보기 + 프로필 열기 + Today + Yesterday + Views + Public Shares + Private Shares + View Stats + View Channel Stats + Message Statistics + Open Message 텔레그램 눈부신 속도 @@ -3244,6 +3345,12 @@ 새로운 메시지 %1$d개 새로운 메시지 %1$d개 새로운 메시지 %1$d개 + %1$d messages unpinned + message unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned 메시지 %1$d개 메시지 %1$d개 메시지 %1$d개 @@ -3400,6 +3507,12 @@ %1$s회 공유 %1$s회 공유 %1$s회 공유 + %1$s public shares + %1$s public share + %1$s public shares + %1$s public shares + %1$s public shares + %1$s public shares %1$s shared %1$s shared %1$s shared @@ -3593,24 +3706,42 @@ %2$d 중 %1$d 선택함 %2$d 중 %1$d 선택함 %2$d 중 %1$d 선택함 - View %1$d Replies - View %1$d Reply - View %1$d Replies - View %1$d Replies - View %1$d Replies - View %1$d Replies - %1$d Replies - %1$d Reply - %1$d Replies - %1$d Replies - %1$d Replies - %1$d Replies - %1$d Comments - %1$d Comment - %1$d Comments - %1$d Comments - %1$d Comments - %1$d Comments + 답글 %1$d 개 보기 + 답글 %1$d 개 보기 + 답글 %1$d 개 보기 + 답글 %1$d 개 보기 + 답글 %1$d 개 보기 + 답글 %1$d 개 보기 + 답글 %1$d 개 + 답글 %1$d 개 + 답글 %1$d 개 + 답글 %1$d 개 + 답글 %1$d 개 + 답글 %1$d 개 + 코멘트 %1$d 개 + 코멘트 %1$d 개 + 코멘트 %1$d 개 + 코멘트 %1$d 개 + 코멘트 %1$d 개 + 코멘트 %1$d 개 + %1$d comments + %1$d comment + %1$d comments + %1$d comments + %1$d comments + %1$d comments + comments + comment + comments + comments + comments + comments + %1$d Pinned Messages + Pinned Message + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages 그룹 채널 @@ -3684,6 +3815,7 @@ 제목 표제 내 위치 + Notify when people sharing location are in range 동영상 품질 종횡비 사진 한 장 더 찍기 @@ -3737,6 +3869,7 @@ 후면 카메라로 전환되었습니다 카메라가 켜져 있습니다 카메라가 꺼져 있습니다 + Pinned message list yyyy년 MMMM yyyy년 MMM dd일 h:mm a @@ -3765,5 +3898,4 @@ \'오늘\' HH:mm\'에 알리기\' MMM d HH:mm\'에 알리기\' yyyy\'년\' M\'월\' d\'일\' HH:mm\'에 알림\' - Today diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index fc2ad3c21..2abab4219 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -226,8 +226,9 @@ Nieuwe chats verbergen? Je ontvangt veel nieuwe chats van mensen die geen contact van je zijn. Wil je deze chats **automatisch dempen** en **archiveren**? GA NAAR INSTELLINGEN - Open Profile + Profiel openen Open Channel + Open Group Send Message Mention Notifications muted @@ -240,7 +241,7 @@ %1$d messages deleted %1$d messages deleted No Results - No Results + Geen resultaten Try a new search. Muziek Bestanden @@ -248,6 +249,8 @@ Voice from all your chats will be shown here. Media Chats + Message pinned + Message unpinned Promoveren tot beheerder Beheerdersrechten aanpassen @@ -563,6 +566,7 @@ Tempolimiet ingeschakeld. Je kunt niet meer dan 1 bericht tegelijkertijd sturen. Tempolimiet ingeschakeld. Je kunt niet meer dan 1 item selecteren. Sorry, deze tekst is te lang om als 1 bericht te sturen.\n\nTempolimiet is ingeschakeld, je kunt niet meer dan 1 bericht tegelijkertijd sturen. + **%1$s** promoted to admin Nieuwe poll Nieuwe quiz @@ -895,9 +899,11 @@ Tik hier om opgeslagen GIF\'s te bekijken Vastzetten Alle leden informeren + Also pin for %1$s Losmaken Bericht vastzetten Bericht losmaken + Do you want to pin an older message while leaving a more recent one pinned? Wil je dit bericht vastzetten? Wil je dit bericht vastzetten? Wil je dit bericht vastzetten bovenaan de chat? @@ -923,6 +929,7 @@ Overig Beschrijving Vastgezet bericht + Previous Message Vastgezette poll gewijzigd Bericht wijzigen @@ -996,7 +1003,7 @@ Tik voor foto, hou vast voor video Tik om als lijst weer te geven. Stuur zonder geluid - Stuur nu> + Stuur nu Plan opnieuw Vandaag Plannen @@ -1042,7 +1049,6 @@ u w to private messages and groups - Transfer Bot Ownership This will transfer the **full owner** rights for the bot to the selected user. Change Owner @@ -1060,6 +1066,10 @@ Choose date This chat helps you keep track of replies to your comments in Channels. Sorry, this post has been removed from the discussion group. + UNPIN ALL MESSAGES + HIDE PINNED MESSAGES + Pinned messages hidden + Pinned messages will be shown again if a new message is pinned. %1$s heeft de zelfvernietigingstimer ingesteld op %2$s Je hebt de zelfvernietigingstimer ingesteld op %1$s @@ -1175,6 +1185,25 @@ %1$s heeft een live-locatie vastgezet %1$s heeft GIF vastgezet %1$s heeft muziekbestand vastgezet + %1$s pinned \"%2$s\" + %1$s pinned a message + %1$s pinned a poll %2$s + %1$s pinned a quiz %2$s + %1$s pinned a photo + %1$s pinned a game + %1$s pinned a game score + %1$s pinned a video + %1$s pinned a file + %1$s pinned an invoice + %1$s pinned a sticker + %1$s pinned a %2$s sticker + %1$s pinned a voice message + %1$s pinned a video message + %1$s pinned a contact %2$s + %1$s pinned a map + %1$s pinned a live location + %1$s pinned a GIF + %1$s pinned an audio file Telegram Contact kiezen @@ -1215,6 +1244,9 @@ Invite friends to try Telegram Find people nearby to chat with Search people by username + New contact + The phone number **%1$s** is not in your contact list. Do you want to add it? + Add contact Mensen toevoegen Je kan meer leden toevoegen nadat je de groep hebt aangemaakt. @@ -1274,7 +1306,7 @@ Uitnodigen voor Telegram %1$s is nog geen lid, uitnodigen? Nodig uit - BLOCK + Blokkeren BLOCK AND DELETE REPLIES Blokkeer Blokkeer gebruiker @@ -2310,6 +2342,12 @@ %1$s km afstand %1$s voet afstand %1$s mijl afstand + %1$s ft + %1$s mi + mi + km + %1$s m + %1$s km %1$s m afstand %1$s km afstand %1$s ft afstand @@ -2343,6 +2381,8 @@ zojuist bijgewerkt Jij en %1$s %1$s aan het delen met %2$s + %1$s sharing with %2$s + %1$s sharing with %2$s ALLES STOPPEN Je deelt je live-locatie met %1$s Kies hoelang je je nauwkeurige locatie met %1$s wilt delen. @@ -2371,6 +2411,19 @@ Stel deze locatie in Mensen kunnen je groep vinden in de \"Mensen Dichtbij\"-sectie Plaatsen in de buurt + Proximity alert + Notify when %1$s is within %2$s + Notify when someone is within %1$s + You are already closer than %1$s + Share Location + Share + For the alert to work, please share your live location in this chat. + Alert when %1$s is close + Alert when other members of the group are close + Proximity alert set + We will notify you once %1$s is within %2$s from you. + We will notify you once someone is within %1$s from you. + Proximity alert cancelled Weergeven als lijst Weergeven als rooster @@ -2478,6 +2531,41 @@ Dit is nu de hoofdgroepsvideo. Photo saved to gallery Video saved to gallery + Photo saved to downloads + Video saved to downloads + GIF saved to downloads + File saved to music + File saved to downloads + %1$d files saved to downloads + File saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d files saved to downloads + %1$d photos saved to gallery + Photo saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d photos saved to gallery + %1$d videos saved to gallery + Video saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d videos saved to gallery + %1$d files saved to music + File saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d files saved to music + %1$d items saved to gallery + One item saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery + %1$d items saved to gallery Twee-staps-verificatie Twee-staps-verificatie @@ -2761,6 +2849,9 @@ un1 is terug in de groep un1 is lid van de groep Je keerde terug naar de groep + un1 is now within %1$s from you + You are now within %1$s from un1 + un1 is now within %1$s from un2 Je hebt deze bot toegestaan je berichten te sturen door in te loggen op %1$s. %1$s heeft de volgende documenten ontvangen: %2$s Persoonlijke gegevens @@ -2937,6 +3028,7 @@ Telegram heeft de toestemming \'over andere apps tekenen\' nodig om video\'s af te spelen in Picture-in-Picture-modus. INSTELLINGEN Sta Telegram toe om weer te kunnen geven op het vergrendelscherm om ervoor te zorgen dat oproepen goed werken. + To share your live location in this chat, Telegram needs access to your location all the time, including while the app is in the background.\n\nWe will access your location only for the duration you choose, and you can stop sharing it any time. We won\'t use your location for any purpose other than sharing it in this chat. Groei Volgers @@ -3010,6 +3102,15 @@ Actiefste dagen Berichten weergeven Profiel openen + Vandaag + Gisteren + Views + Public Shares + Private Shares + View Stats + View Channel Stats + Message Statistics + Open Message Telegram Snel @@ -3244,6 +3345,12 @@ %1$d nieuwe berichten %1$d nieuwe berichten %1$d nieuwe berichten + %1$d messages unpinned + message unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned + %1$d messages unpinned %1$d berichten %1$d bericht %1$d berichten @@ -3400,6 +3507,12 @@ %1$s keer gedeeld %1$s keer gedeeld %1$s keer gedeeld + %1$s public shares + %1$s public share + %1$s public shares + %1$s public shares + %1$s public shares + %1$s public shares %1$s shared %1$s shared %1$s shared @@ -3611,6 +3724,24 @@ %1$d Comments %1$d Comments %1$d Comments + %1$d comments + %1$d comment + %1$d comments + %1$d comments + %1$d comments + %1$d comments + comments + comment + comments + comments + comments + comments + %1$d Pinned Messages + Pinned Message + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages + %1$d Pinned Messages Groep Kanaal @@ -3684,6 +3815,7 @@ Titel Titel Mijn locatie + Notify when people sharing location are in range Videokwaliteit Beelverhouding Nog een foto nemen @@ -3737,6 +3869,7 @@ Overgeschakeld naar de achtercamera De camera staat aan De camera staat uit + Pinned message list MMMM yyyy dd MMM yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'Herinner vandaag om HH:mm \'Herinner op\' d MMM \'om\' HH:mm \'Herinner op\' d MMM yyyy \'om\' HH:mm - Today diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index dfc26bf75..c54ad83e5 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -228,6 +228,7 @@ ABRIR CONFIGURAÇÕES Abrir Perfil Abrir Canal + Abrir Grupo Enviar Mensagem Mencionar Notificações silenciadas @@ -242,12 +243,14 @@ Sem Resultados Sem Resultados Tente uma nova busca. - Músicas - Arquivos - Links - Voz - Mídias + Músicas de todos os seus chats aparecerão aqui. + Arquivos de todos os seus chats aparecerão aqui. + Links de todos os seus chats aparecerão aqui. + Voz de todos os seus chats aparecerão aqui. + Mídias de todos os seus chats aparecerão aqui. Chats + Mensagem fixada + Mensagem desafixada Promover a administrador Editar permissões de admin @@ -368,7 +371,7 @@ Vídeo do canal alterado Foto do canal removida Nome do canal alterado para un2 - Desculpe, você reservou muitos nomes públicos. Você pode remover o link público de um de seus grupos ou canais, ou criar de forma privada. + Desculpe, você reservou muitos nomes públicos. Você pode remover o link público de um dos seus grupos ou canais, ou criar de forma privada. Dono Administrador Admin @@ -563,6 +566,7 @@ O Modo Lento está ativado. Você não pode enviar mais de uma mensagem por vez. O Modo Lento está ativado. Você não pode selecionar mais itens. Desculpe, este texto é muito longo para ser enviado em uma só mensagem.\n\nO Modo Lento está ativado. Você não pode enviar mais de uma mensagem por vez. + **%1$s** promovido a admin Nova Enquete Novo Quiz @@ -895,12 +899,14 @@ Toque aqui para acessar os GIFs salvos Fixar Notificar todos os membros + Fixar para %1$s também Desafixar Fixar mensagem Desafixar mensagem - Deseja fixar essa mensagem no grupo? + Deseja fixar uma mensagem mais antiga enquanto deixa a mais recente fixada? + Deseja fixar a mensagem para todos os membros do grupo? Deseja fixar essa mensagem no canal? - Deseja fixar essa mensagem no topo do seu chat de Mensagens Salvas? + Deseja fixar essa mensagem no topo do chat? Deseja desafixar essa mensagem? Banir usuário Denunciar spam @@ -923,6 +929,7 @@ Outro Descrição Mensagem fixada + Mensagem Anterior Enquete fixada editada Editar Mensagem @@ -996,7 +1003,7 @@ Toque para foto, segure para vídeo Toque para ver em lista. Enviar sem som - Enviar Agora> + Enviar Agora Reagendar Hoje Agendar @@ -1042,14 +1049,13 @@ h S para mensagens privadas e grupos - Transferir Posse do Bot Isso vai transferir todos os direitos de **dono** do bot para o usuário selecionado. Alterar Dono Você pode transferir este bot somente se tiver: Deixe um comentário Comentários - Comentário + Comentar Respostas Nenhum comentário ainda... Nenhuma resposta ainda... @@ -1059,7 +1065,11 @@ Ver Tópico Escolher data Este chat te ajuda a acompanhar as respostas aos comentários que você fez nos canais. - Sorry, this post has been removed from the discussion group. + Desculpe, esse post foi removido do grupo de conversa. + DESAFIXAR TUDO + OCULTAR MENSAGENS FIXADAS + Mensagens fixadas ocultadas + As mensagens fixadas só aparecerão de novo se uma nova mensagem for fixada. "%1$s alterou o timer de autodestruição para %2$s " Você alterou o timer de autodestruição para %1$s @@ -1175,6 +1185,25 @@ %1$s fixou uma localização em tempo real %1$s fixou um GIF %1$s fixou um arquivo de áudio + %1$s fixou \"%2$s\" + %1$s fixou uma mensagem + %1$s fixou a enquete %2$s + %1$s fixou o quiz %2$s + %1$s fixou uma foto + %1$s fixou um jogo + %1$s fixou uma pontuação de jogo + %1$s fixou um vídeo + %1$s fixou um arquivo + %1$s fixou uma fatura + %1$s fixou um sticker + %1$s fixou o sticker %2$s + %1$s fixou uma mensagem de voz + %1$s fixou uma mensagem de vídeo + %1$s fixou o contato %2$s + %1$s fixou um mapa + %1$s fixou uma localização ao vivo + %1$s fixou um GIF + %1$s fixou um arquivo de áudio Telegram Selecione um Contato @@ -1213,8 +1242,11 @@ Número de telefone Você ainda não tem contatos no Telegram Convide amigos para testar o Telegram - Encontre pessoas próximas para conversar + Encontre pessoas próximas Busque pessoas por nome de usuário + Novo contato + O número de **%1$s** não está nos seus contatos. Deseja adicionar? + Adicionar contato Adicionar pessoas... Você poderá adicionar mais membros depois de criar o grupo. @@ -2310,6 +2342,12 @@ %1$s km de distância %1$s pés de distância %1$s milhas de distância + %1$s pés + %1$s mi + mi + km + %1$s m + %1$s km %1$s m de você %1$s km de você %1$s pés de você @@ -2343,6 +2381,8 @@ atualizado agora Você e %1$s %1$s com %2$s + %1$s com %2$s + %1$s com %2$s PARAR TODOS Compartilhando a Localização com %1$s Escolha por quanto tempo %1$s verá sua localização precisa. @@ -2371,6 +2411,19 @@ Definir esta localização As pessoas poderão encontrar seu grupo na seção \"Pessoas Próximas\". Lugares por aqui + Alerta de proximidade + Notificar quando %1$s estiver a %2$s + Notificar quando alguém estiver a %1$s + Você já está mais perto que %1$s + Compartilhar Localização + Compartilhar + Para o alerta funcionar, compartilhe a sua localização em tempo real neste chat. + Alertar quando %1$s estiver perto + Alertar quando outros participantes estiverem perto + Alerta de proximidade ativado + Vamos te notificar quando %1$s estiver a %2$s de você. + We will notify you once someone is within %1$s from you. + Alerta de proximidade cancelado Exibir em lista Exibir em grade @@ -2478,6 +2531,41 @@ Este é o vídeo principal do grupo agora. Foto salva na galeria Vídeo salvo na galeria + Foto salva em downloads + Vídeo salvo em downloads + GIF salvo em downloads + Arquivo salvo nas músicas + Arquivo salvo em downloads + %1$d arquivos salvos em downloads + Arquivo salvo em downloads + %1$d arquivos salvos em downloads + %1$d arquivos salvos em downloads + %1$d arquivos salvos em downloads + %1$d arquivos salvos em downloads + %1$d fotos salvas na galeria + Foto salva na galeria + %1$d fotos salvas na galeria + %1$d fotos salvas na galeria + %1$d fotos salvas na galeria + %1$d fotos salvas na galeria + %1$d vídeos salvos na galeria + Vídeo salvo na galeria + %1$d vídeos salvos na galeria + %1$d vídeos salvos na galeria + %1$d vídeos salvos na galeria + %1$d vídeos salvos na galeria + %1$d arquivos salvos nas músicas + Arquivo salvo nas músicas + %1$d arquivos salvos nas músicas + %1$d arquivos salvos nas músicas + %1$d arquivos salvos nas músicas + %1$d arquivos salvos nas músicas + %1$d itens salvos na galeria + Um item salvo na galeria + %1$d itens salvos na galeria + %1$d itens salvos na galeria + %1$d itens salvos na galeria + %1$d itens salvos na galeria Verificação em Duas Etapas Verificação em Duas Etapas @@ -2761,6 +2849,9 @@ un1 retornou ao grupo un1 entrou no grupo Você retornou ao grupo + un1 está a %1$s de você + Você está a %1$s de un1 + un1 está agora a %1$s de un2 Você permitiu que o bot te envie mensagens ao fazer o login em %1$s. %1$s recebeu os seguintes documentos: %2$s Dados pessoais @@ -2863,7 +2954,7 @@ Isso irá enviar sua localização atual ao bot. O app não conseguiu determinar a sua localização atual. Escolher manualmente - Esse bot gostaria de saber sua localização todas as vezes que você enviá-lo uma mensagem. Isso pode ser utilizado para providenciar resultados específicos de localização. + Este bot gostaria de saber a sua localização sempre que você o usar. Isso pode ser utilizado para mostrar resultados baseados em localização. Compartilhar seu número de telefone? O bot saberá seu número de telefone. Isso pode ser útil para a integração com outros serviços. Deseja compartilhar o seu número de telefone %1$s com **%2$s**? @@ -2937,6 +3028,7 @@ Para reproduzir vídeos no modo PiP, o Telegram precisa de acesso para aparecer sobre outros apps. CONFIGURAÇÕES Por favor, permita que o Telegram seja mostrado na tela de bloqueio para que as chamadas possam funcionar corretamente. + Para enviar a sua localização em tempo real neste chat, o Telegram precisa de acesso contínuo à sua localização, inclusive enquanto o app estiver em segundo plano.\n\nO Telegram acessará a sua localização somente pela duração que você escolher e você pode parar de compartilhar a qualquer momento. Não usaremos a sua localização para nenhum outro motivo além de compartilhar neste chat. Crescimento Inscritos @@ -3010,6 +3102,15 @@ Dias da semana Ver Mensagens Ver Perfil + Hoje + Ontem + Visualizações + Compartilhamentos Públicos + Compartilhamentos Privados + Ver Estatísticas + Ver Estatísticas do Canal + Estatísticas da Mensagem + Abrir Mensagem Telegram Rápido @@ -3244,6 +3345,12 @@ %1$d novas mensagens %1$d novas mensagens %1$d novas mensagens + %1$d mensagens desafixadas + mensagem desafixada + %1$d mensagens desafixadas + %1$d mensagens desafixadas + %1$d mensagens desafixadas + %1$d mensagens desafixadas %1$d mensagens %1$d mensagem %1$d mensagens @@ -3400,6 +3507,12 @@ %1$s compartilhamentos %1$s compartilhamentos %1$s compartilhamentos + %1$s compartilhamentos públicos + %1$s compartilhamento público + %1$s compartilhamentos públicos + %1$s compartilhamentos públicos + %1$s compartilhamentos públicos + %1$s compartilhamentos públicos %1$s compartilhados %1$s compartilhado %1$s compartilhados @@ -3611,6 +3724,24 @@ %1$d Comentários %1$d Comentários %1$d Comentários + %1$d comentários + %1$d comentário + %1$d comentários + %1$d comentários + %1$d comentários + %1$d comentários + comentários + comentário + comentários + comentários + comentários + comentários + %1$d Mensagens Fixadas + Mensagem Fixada + %1$d Mensagens Fixadas + %1$d Mensagens Fixadas + %1$d Mensagens Fixadas + %1$d Mensagens Fixadas Grupo Canal @@ -3684,6 +3815,7 @@ Título Cabeçalho Minha localização + Notificar quando pessoas que compartilham a localização estiverem perto Qualidade do vídeo Proporção da imagem Tirar mais uma foto @@ -3737,6 +3869,7 @@ Alternou para a câmera traseira Câmera ligada Câmera desligada + Lista de mensagens fixadas MMMM \'de\' yyyy dd \'de\' MMM \'de\' yyyy, h:mm a @@ -3765,5 +3898,4 @@ \'Lembrar hoje às\' HH:mm \'Lembrar em\' d \'de\' MMM \'às\' HH:mm \'Lembrar em\' d \'de\' MMM \'de\' yyyy \'às\' HH:mm - Today diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index f543f19d9..2d518a831 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2420,6 +2420,10 @@ For the alert to work, please share your live location in this chat. Alert when %1$s is close Alert when other members of the group are close + Proximity alert set + We will notify you once %1$s is within %2$s from you. + We will notify you once someone is within %1$s from you. + Proximity alert cancelled Show as list Show as grid